diff --git a/lib/libcxx/include/__algorithm/adjacent_find.h b/lib/libcxx/include/__algorithm/adjacent_find.h index 30df4a976f..7819e2cf49 100644 --- a/lib/libcxx/include/__algorithm/adjacent_find.h +++ b/lib/libcxx/include/__algorithm/adjacent_find.h @@ -20,6 +20,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -50,4 +53,6 @@ adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_ADJACENT_FIND_H diff --git a/lib/libcxx/include/__algorithm/all_of.h b/lib/libcxx/include/__algorithm/all_of.h index 284c34ffcd..237f8495c6 100644 --- a/lib/libcxx/include/__algorithm/all_of.h +++ b/lib/libcxx/include/__algorithm/all_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/lib/libcxx/include/__algorithm/binary_search.h b/lib/libcxx/include/__algorithm/binary_search.h index 8f958c2c1a..0c8f5545e0 100644 --- a/lib/libcxx/include/__algorithm/binary_search.h +++ b/lib/libcxx/include/__algorithm/binary_search.h @@ -37,8 +37,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::binary_search(__first, __last, __value, - __less::value_type, _Tp>()); + return std::binary_search(__first, __last, __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/clamp.h b/lib/libcxx/include/__algorithm/clamp.h index 30ddbdce64..31deb4fd94 100644 --- a/lib/libcxx/include/__algorithm/clamp.h +++ b/lib/libcxx/include/__algorithm/clamp.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) { - _LIBCPP_ASSERT(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; } @@ -37,7 +37,7 @@ _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) { - return _VSTD::clamp(__v, __lo, __hi, __less<_Tp>()); + return _VSTD::clamp(__v, __lo, __hi, __less<>()); } #endif diff --git a/lib/libcxx/include/__algorithm/comp.h b/lib/libcxx/include/__algorithm/comp.h index af8eb7b5d7..9474536615 100644 --- a/lib/libcxx/include/__algorithm/comp.h +++ b/lib/libcxx/include/__algorithm/comp.h @@ -10,6 +10,8 @@ #define _LIBCPP___ALGORITHM_COMP_H #include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/predicate_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,41 +26,20 @@ struct __equal_to { } }; -template -struct __less -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +template +struct __is_trivial_equality_predicate<__equal_to, _Lhs, _Rhs> : true_type {}; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;} +// The definition is required because __less is part of the ABI, but it's empty +// because all comparisons should be transparent. +template +struct __less {}; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;} - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;} -}; - -template -struct __less<_T1, _T1> -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} -}; - -template -struct __less -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} -}; - -template -struct __less<_T1, const _T1> -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +template <> +struct __less { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _Tp& __lhs, const _Up& __rhs) const { + return __lhs < __rhs; + } }; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/comp_ref_type.h b/lib/libcxx/include/__algorithm/comp_ref_type.h index f2338e1446..d16bd0f531 100644 --- a/lib/libcxx/include/__algorithm/comp_ref_type.h +++ b/lib/libcxx/include/__algorithm/comp_ref_type.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_COMP_REF_TYPE_H #define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H +#include <__assert> #include <__config> -#include <__debug> #include <__utility/declval.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,11 +23,10 @@ template struct __debug_less { _Compare &__comp_; - _LIBCPP_CONSTEXPR_SINCE_CXX14 - __debug_less(_Compare& __c) : __comp_(__c) {} + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI __debug_less(_Compare& __c) : __comp_(__c) {} template - _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Up& __y) { bool __r = __comp_(__x, __y); @@ -37,7 +36,7 @@ struct __debug_less } template - _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(_Tp& __x, _Up& __y) { bool __r = __comp_(__x, __y); @@ -52,7 +51,7 @@ struct __debug_less decltype((void)std::declval<_Compare&>()( std::declval<_LHS &>(), std::declval<_RHS &>())) __do_compare_assert(int, _LHS & __l, _RHS & __r) { - _LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r), + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering"); (void)__l; (void)__r; @@ -66,7 +65,7 @@ struct __debug_less // Pass the comparator by lvalue reference. Or in debug mode, using a // debugging wrapper that stores a reference. -#ifdef _LIBCPP_ENABLE_DEBUG_MODE +#if _LIBCPP_ENABLE_DEBUG_MODE template using __comp_ref_type = __debug_less<_Comp>; #else diff --git a/lib/libcxx/include/__algorithm/copy.h b/lib/libcxx/include/__algorithm/copy.h index 193a6df316..dfe9898c64 100644 --- a/lib/libcxx/include/__algorithm/copy.h +++ b/lib/libcxx/include/__algorithm/copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___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> @@ -44,36 +45,34 @@ struct __copy_loop { return std::make_pair(std::move(__first), std::move(__result)); } + template + struct _CopySegment { + using _Traits = __segmented_iterator_traits<_InIter>; + + _OutIter& __result_; + + _LIBCPP_HIDE_FROM_ABI _CopySegment(_OutIter& __result) : __result_(__result) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { + __result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; + } + }; + template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { - using _Traits = __segmented_iterator_traits<_InIter>; - auto __sfirst = _Traits::__segment(__first); - auto __slast = _Traits::__segment(__last); - if (__sfirst == __slast) { - auto __iters = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); - return std::make_pair(__last, std::move(__iters.second)); - } - - __result = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - while (__sfirst != __slast) { - __result = - std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - } - __result = - std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + std::__for_each_segment(__first, __last, _CopySegment<_InIter, _OutIter>(__result)); return std::make_pair(__last, std::move(__result)); } template ::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; @@ -98,8 +97,7 @@ struct __copy_loop { struct __copy_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. - template ::value, int> = 0> + template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> operator()(_In* __first, _In* __last, _Out* __result) const { return std::__copy_trivial_impl(__first, __last, __result); diff --git a/lib/libcxx/include/__algorithm/copy_backward.h b/lib/libcxx/include/__algorithm/copy_backward.h index bb2a432878..d85d297b32 100644 --- a/lib/libcxx/include/__algorithm/copy_backward.h +++ b/lib/libcxx/include/__algorithm/copy_backward.h @@ -76,11 +76,11 @@ struct __copy_backward_loop { template ::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; auto __orig_last = __last; auto __segment_iterator = _Traits::__segment(__result); diff --git a/lib/libcxx/include/__algorithm/copy_move_common.h b/lib/libcxx/include/__algorithm/copy_move_common.h index b88c14911b..c06892e9e3 100644 --- a/lib/libcxx/include/__algorithm/copy_move_common.h +++ b/lib/libcxx/include/__algorithm/copy_move_common.h @@ -15,6 +15,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> +#include <__string/constexpr_c_functions.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_always_bitcastable.h> #include <__type_traits/is_constant_evaluated.h> @@ -61,7 +62,8 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> __copy_trivial_impl(_In* __first, _In* __last, _Out* __result) { const size_t __n = static_cast(__last - __first); - ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + std::__constexpr_memmove(__result, __first, __element_count(__n)); return std::make_pair(__last, __result + __n); } @@ -72,7 +74,7 @@ __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { const size_t __n = static_cast(__last - __first); __result -= __n; - ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + std::__constexpr_memmove(__result, __first, __element_count(__n)); return std::make_pair(__last, __result); } @@ -119,16 +121,6 @@ __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); } -template -struct __can_copy_without_conversion : false_type {}; - -template -struct __can_copy_without_conversion< - _IterOps, - _InValue, - _OutIter, - __enable_if_t >::value> > : true_type {}; - template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> __dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { -#ifdef _LIBCPP_COMPILER_GCC - // GCC doesn't support `__builtin_memmove` during constant evaluation. - if (__libcpp_is_constant_evaluated()) { - return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); - } -#else - // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is - // insufficient). Also, conversions are not supported. - if (__libcpp_is_constant_evaluated()) { - using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>; - if (!is_trivially_copyable<_InValue>::value || - !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) { - return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); - } - } -#endif // _LIBCPP_COMPILER_GCC - using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); } diff --git a/lib/libcxx/include/__algorithm/copy_n.h b/lib/libcxx/include/__algorithm/copy_n.h index b08bbdfb9b..f3701662aa 100644 --- a/lib/libcxx/include/__algorithm/copy_n.h +++ b/lib/libcxx/include/__algorithm/copy_n.h @@ -12,8 +12,8 @@ #include <__algorithm/copy.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> #include <__utility/convert_to_integral.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -25,8 +25,8 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_input_iterator<_InputIterator>::value && - !__is_cpp17_random_access_iterator<_InputIterator>::value, + __has_input_iterator_category<_InputIterator>::value && + !__has_random_access_iterator_category<_InputIterator>::value, _OutputIterator >::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) @@ -51,7 +51,7 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_random_access_iterator<_InputIterator>::value, + __has_random_access_iterator_category<_InputIterator>::value, _OutputIterator >::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) diff --git a/lib/libcxx/include/__algorithm/equal.h b/lib/libcxx/include/__algorithm/equal.h index cf37f46aaf..b69aeff92b 100644 --- a/lib/libcxx/include/__algorithm/equal.h +++ b/lib/libcxx/include/__algorithm/equal.h @@ -11,9 +11,20 @@ #define _LIBCPP___ALGORITHM_EQUAL_H #include <__algorithm/comp.h> +#include <__algorithm/unwrap_iter.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__string/constexpr_c_functions.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/predicate_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,23 +33,42 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) { for (; __first1 != __last1; ++__first1, (void)++__first2) if (!__pred(*__first1, *__first2)) return false; return true; } +template < + class _Tp, + class _Up, + class _BinaryPredicate, + __enable_if_t<__is_trivial_equality_predicate<_BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value && + !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + int> = 0> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) { + return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); +} + +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { + return std::__equal_iter_impl( + std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); +} + template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::equal(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) { for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) @@ -47,19 +77,52 @@ __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fir return __first1 == __last1 && __first2 == __last2; } +template +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( + _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) { + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + return false; + ++__first1; + ++__first2; + } + return __first1 == __last1 && __first2 == __last2; +} + +template ::value && __is_identity<_Proj1>::value && + __is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value && + __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + int> = 0> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( + _Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) { + return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); +} + template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, random_access_iterator_tag) { if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) return false; - return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, - _BinaryPredicate&>(__first1, __last1, __first2, __pred); + __identity __proj; + return std::__equal_impl( + std::__unwrap_iter(__first1), + std::__unwrap_iter(__last1), + std::__unwrap_iter(__first2), + std::__unwrap_iter(__last2), + __pred, + __proj, + __proj); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred) { return _VSTD::__equal<_BinaryPredicate&>( @@ -68,7 +131,7 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::__equal( __first1, diff --git a/lib/libcxx/include/__algorithm/equal_range.h b/lib/libcxx/include/__algorithm/equal_range.h index 2075b03412..dc1268a6ff 100644 --- a/lib/libcxx/include/__algorithm/equal_range.h +++ b/lib/libcxx/include/__algorithm/equal_range.h @@ -50,7 +50,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } else { _Iter __mp1 = __mid; return pair<_Iter, _Iter>( - std::__lower_bound_impl<_AlgPolicy>(__first, __mid, __value, __comp, __proj), + std::__lower_bound<_AlgPolicy>(__first, __mid, __value, __comp, __proj), std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj)); } } @@ -75,11 +75,7 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu template _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::equal_range( - std::move(__first), - std::move(__last), - __value, - __less::value_type, _Tp>()); + return std::equal_range(std::move(__first), std::move(__last), __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/fill.h b/lib/libcxx/include/__algorithm/fill.h index 76cf4a1477..0753c427ae 100644 --- a/lib/libcxx/include/__algorithm/fill.h +++ b/lib/libcxx/include/__algorithm/fill.h @@ -12,7 +12,6 @@ #include <__algorithm/fill_n.h> #include <__config> #include <__iterator/iterator_traits.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/fill_n.h b/lib/libcxx/include/__algorithm/fill_n.h index fe58c8d641..e7863ac7ec 100644 --- a/lib/libcxx/include/__algorithm/fill_n.h +++ b/lib/libcxx/include/__algorithm/fill_n.h @@ -12,7 +12,6 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/convert_to_integral.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/find.h b/lib/libcxx/include/__algorithm/find.h index e51dc9bb16..e0de503287 100644 --- a/lib/libcxx/include/__algorithm/find.h +++ b/lib/libcxx/include/__algorithm/find.h @@ -10,7 +10,16 @@ #ifndef _LIBCPP___ALGORITHM_FIND_H #define _LIBCPP___ALGORITHM_FIND_H +#include <__algorithm/unwrap_iter.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__string/constexpr_c_functions.h> +#include <__type_traits/is_same.h> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include +#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,13 +27,49 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter +__find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + break; + return __first; +} + +template ::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && + sizeof(_Tp) == 1, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* +__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { + if (auto __ret = std::__constexpr_memchr(__first, __value, __last - __first)) + return __ret; + return __last; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template ::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && + sizeof(_Tp) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t), + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* +__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { + if (auto __ret = std::__constexpr_wmemchr(__first, __value, __last - __first)) + return __ret; + return __last; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { - for (; __first != __last; ++__first) - if (*__first == __value) - break; - return __first; + __identity __proj; + return std::__rewrap_iter( + __first, std::__find_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __value, __proj)); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/find_end.h b/lib/libcxx/include/__algorithm/find_end.h index e2fee6b3c4..edb9891c66 100644 --- a/lib/libcxx/include/__algorithm/find_end.h +++ b/lib/libcxx/include/__algorithm/find_end.h @@ -15,12 +15,12 @@ #include <__algorithm/search.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__iterator/reverse_iterator.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/for_each_n.h b/lib/libcxx/include/__algorithm/for_each_n.h index 38d204a118..5bd7318224 100644 --- a/lib/libcxx/include/__algorithm/for_each_n.h +++ b/lib/libcxx/include/__algorithm/for_each_n.h @@ -12,7 +12,6 @@ #include <__config> #include <__utility/convert_to_integral.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator for_each_n(_InputIterator __first, diff --git a/lib/libcxx/include/__algorithm/for_each_segment.h b/lib/libcxx/include/__algorithm/for_each_segment.h new file mode 100644 index 0000000000..93aa8259b2 --- /dev/null +++ b/lib/libcxx/include/__algorithm/for_each_segment.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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_SEGMENT_H +#define _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H + +#include <__config> +#include <__iterator/segmented_iterator.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __for_each_segment is a utility function for optimizing iterating over segmented iterators linearly. +// __first and __last are expected to be a segmented range. __func is expected to take a range of local iterators. +// Anything that is returned from __func is ignored. + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__for_each_segment(_SegmentedIterator __first, _SegmentedIterator __last, _Functor __func) { + using _Traits = __segmented_iterator_traits<_SegmentedIterator>; + + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + + // We are in a single segment, so we might not be at the beginning or end + if (__sfirst == __slast) { + __func(_Traits::__local(__first), _Traits::__local(__last)); + return; + } + + // We have more than one segment. Iterate over the first segment, since we might not start at the beginning + __func(_Traits::__local(__first), _Traits::__end(__sfirst)); + ++__sfirst; + // iterate over the segments which are guaranteed to be completely in the range + while (__sfirst != __slast) { + __func(_Traits::__begin(__sfirst), _Traits::__end(__sfirst)); + ++__sfirst; + } + // iterate over the last segment + __func(_Traits::__begin(__sfirst), _Traits::__local(__last)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H diff --git a/lib/libcxx/include/__algorithm/generate_n.h b/lib/libcxx/include/__algorithm/generate_n.h index 45259989bf..ff5c82d3e4 100644 --- a/lib/libcxx/include/__algorithm/generate_n.h +++ b/lib/libcxx/include/__algorithm/generate_n.h @@ -11,7 +11,6 @@ #include <__config> #include <__utility/convert_to_integral.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/half_positive.h b/lib/libcxx/include/__algorithm/half_positive.h index 74aede2b56..5a0f4baf6a 100644 --- a/lib/libcxx/include/__algorithm/half_positive.h +++ b/lib/libcxx/include/__algorithm/half_positive.h @@ -10,7 +10,9 @@ #define _LIBCPP___ALGORITHM_HALF_POSITIVE_H #include <__config> -#include +#include <__type_traits/enable_if.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/make_unsigned.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/in_found_result.h b/lib/libcxx/include/__algorithm/in_found_result.h index 3134d6e0df..d9ca287f01 100644 --- a/lib/libcxx/include/__algorithm/in_found_result.h +++ b/lib/libcxx/include/__algorithm/in_found_result.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,6 +44,6 @@ struct in_found_result { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H diff --git a/lib/libcxx/include/__algorithm/in_fun_result.h b/lib/libcxx/include/__algorithm/in_fun_result.h index 3cbb9e12d3..33374eddc3 100644 --- a/lib/libcxx/include/__algorithm/in_fun_result.h +++ b/lib/libcxx/include/__algorithm/in_fun_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -42,7 +42,7 @@ struct in_fun_result { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/in_in_out_result.h b/lib/libcxx/include/__algorithm/in_in_out_result.h index 3e747be44d..6b50e0e245 100644 --- a/lib/libcxx/include/__algorithm/in_in_out_result.h +++ b/lib/libcxx/include/__algorithm/in_in_out_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -49,7 +49,7 @@ struct in_in_out_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/in_in_result.h b/lib/libcxx/include/__algorithm/in_in_result.h index 2098c188cc..1eceb9de02 100644 --- a/lib/libcxx/include/__algorithm/in_in_result.h +++ b/lib/libcxx/include/__algorithm/in_in_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -46,7 +46,7 @@ struct in_in_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/in_out_out_result.h b/lib/libcxx/include/__algorithm/in_out_out_result.h index 4046eee57d..2f7a09b5c3 100644 --- a/lib/libcxx/include/__algorithm/in_out_out_result.h +++ b/lib/libcxx/include/__algorithm/in_out_out_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -47,7 +47,7 @@ struct in_out_out_result { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/in_out_result.h b/lib/libcxx/include/__algorithm/in_out_result.h index 7f5a0271b4..e4741cb71f 100644 --- a/lib/libcxx/include/__algorithm/in_out_result.h +++ b/lib/libcxx/include/__algorithm/in_out_result.h @@ -18,9 +18,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -46,8 +49,10 @@ struct in_out_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_IN_OUT_RESULT_H diff --git a/lib/libcxx/include/__algorithm/includes.h b/lib/libcxx/include/__algorithm/includes.h index cc39f275bf..88253e2653 100644 --- a/lib/libcxx/include/__algorithm/includes.h +++ b/lib/libcxx/include/__algorithm/includes.h @@ -61,13 +61,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { - return std::includes( - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__last2), - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + return std::includes(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/inplace_merge.h b/lib/libcxx/include/__algorithm/inplace_merge.h index 5bbefc94bd..44a9425559 100644 --- a/lib/libcxx/include/__algorithm/inplace_merge.h +++ b/lib/libcxx/include/__algorithm/inplace_merge.h @@ -246,8 +246,7 @@ inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { - std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), - __less::value_type>()); + std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/is_heap.h b/lib/libcxx/include/__algorithm/is_heap.h index 2dcb4a28e8..93d84d3380 100644 --- a/lib/libcxx/include/__algorithm/is_heap.h +++ b/lib/libcxx/include/__algorithm/is_heap.h @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - return _VSTD::is_heap(__first, __last, __less::value_type>()); + return _VSTD::is_heap(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/is_heap_until.h b/lib/libcxx/include/__algorithm/is_heap_until.h index 6ed4cb29c4..d7131114bd 100644 --- a/lib/libcxx/include/__algorithm/is_heap_until.h +++ b/lib/libcxx/include/__algorithm/is_heap_until.h @@ -58,7 +58,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) { - return _VSTD::__is_heap_until(__first, __last, __less::value_type>()); + return _VSTD::__is_heap_until(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/is_permutation.h b/lib/libcxx/include/__algorithm/is_permutation.h index 005445652e..105a073228 100644 --- a/lib/libcxx/include/__algorithm/is_permutation.h +++ b/lib/libcxx/include/__algorithm/is_permutation.h @@ -19,19 +19,22 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__type_traits/is_callable.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template struct _ConstTimeDistance : false_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< @@ -47,7 +50,7 @@ struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< is_same::iterator_category, random_access_iterator_tag>::value > > : true_type {}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // Internal functions @@ -202,7 +205,7 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt return std::is_permutation(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // 2+2 iterators template @@ -231,8 +234,10 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt __pred, __identity(), __identity()); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/is_sorted.h b/lib/libcxx/include/__algorithm/is_sorted.h index bf44f45764..a321c2c12d 100644 --- a/lib/libcxx/include/__algorithm/is_sorted.h +++ b/lib/libcxx/include/__algorithm/is_sorted.h @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::is_sorted(__first, __last, __less::value_type>()); + return _VSTD::is_sorted(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/is_sorted_until.h b/lib/libcxx/include/__algorithm/is_sorted_until.h index b6683000a0..890b93631c 100644 --- a/lib/libcxx/include/__algorithm/is_sorted_until.h +++ b/lib/libcxx/include/__algorithm/is_sorted_until.h @@ -48,7 +48,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::is_sorted_until(__first, __last, __less::value_type>()); + return _VSTD::is_sorted_until(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/iterator_operations.h b/lib/libcxx/include/__algorithm/iterator_operations.h index bd3e6f1d38..002978014c 100644 --- a/lib/libcxx/include/__algorithm/iterator_operations.h +++ b/lib/libcxx/include/__algorithm/iterator_operations.h @@ -33,11 +33,14 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template struct _IterOps; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _RangeAlgPolicy {}; template <> @@ -172,4 +175,6 @@ struct _IterOps<_ClassicAlgPolicy> { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H diff --git a/lib/libcxx/include/__algorithm/lexicographical_compare.h b/lib/libcxx/include/__algorithm/lexicographical_compare.h index 0a13c5dd31..62b72edc80 100644 --- a/lib/libcxx/include/__algorithm/lexicographical_compare.h +++ b/lib/libcxx/include/__algorithm/lexicographical_compare.h @@ -52,9 +52,7 @@ bool lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { - return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/lib/libcxx/include/__algorithm/lexicographical_compare_three_way.h new file mode 100644 index 0000000000..32de97d07a --- /dev/null +++ b/lib/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// 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_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H +#define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H + +#include <__algorithm/min.h> +#include <__algorithm/three_way_comp_ref_type.h> +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_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> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// Fast path for random access iterators which computes the number of loop iterations up-front and +// then skips the iterator comparisons inside the loop. +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_path( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) + -> decltype(__comp(*__first1, *__first2)) { + static_assert( + signed_integral<__iter_diff_t<_InputIterator1>>, "Using a non-integral difference_type is undefined behavior."); + static_assert( + signed_integral<__iter_diff_t<_InputIterator2>>, "Using a non-integral difference_type is undefined behavior."); + + using _Len1 = __iter_diff_t<_InputIterator1>; + using _Len2 = __iter_diff_t<_InputIterator2>; + using _Common = common_type_t<_Len1, _Len2>; + + _Len1 __len1 = __last1 - __first1; + _Len2 __len2 = __last2 - __first2; + _Common __min_len = std::min<_Common>(__len1, __len2); + + for (_Common __i = 0; __i < __min_len; ++__i) { + auto __c = __comp(*__first1, *__first2); + if (__c != 0) { + return __c; + } + ++__first1; + ++__first2; + } + + return __len1 <=> __len2; +} + +// Unoptimized implementation which compares the iterators against the end in every loop iteration +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_path( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) + -> decltype(__comp(*__first1, *__first2)) { + while (true) { + bool __exhausted1 = __first1 == __last1; + bool __exhausted2 = __first2 == __last2; + + if (__exhausted1 || __exhausted2) { + if (!__exhausted1) + return strong_ordering::greater; + if (!__exhausted2) + return strong_ordering::less; + return strong_ordering::equal; + } + + auto __c = __comp(*__first1, *__first2); + if (__c != 0) { + return __c; + } + + ++__first1; + ++__first2; + } +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) + -> decltype(__comp(*__first1, *__first2)) { + static_assert(__comparison_category, + "The comparator passed to lexicographical_compare_three_way must return a comparison category type."); + static_assert(std::is_copy_constructible_v<_InputIterator1>, "Iterators must be copy constructible."); + static_assert(std::is_copy_constructible_v<_InputIterator2>, "Iterators must be copy constructible."); + __three_way_comp_ref_type<_Cmp> __wrapped_comp_ref(__comp); + if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && + __has_random_access_iterator_category<_InputIterator2>::value) { + return std::__lexicographical_compare_three_way_fast_path( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); + } else { + // Unoptimized implementation which compares the iterators against the end in every loop iteration + return std::__lexicographical_compare_three_way_slow_path( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); + } +} + +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::lexicographical_compare_three_way( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H diff --git a/lib/libcxx/include/__algorithm/lower_bound.h b/lib/libcxx/include/__algorithm/lower_bound.h index 2648982ea5..91c3bdaafd 100644 --- a/lib/libcxx/include/__algorithm/lower_bound.h +++ b/lib/libcxx/include/__algorithm/lower_bound.h @@ -20,7 +20,6 @@ #include <__iterator/iterator_traits.h> #include <__type_traits/is_callable.h> #include <__type_traits/remove_reference.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 -_Iter __lower_bound_impl(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { +_Iter __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); while (__len != 0) { @@ -53,14 +52,13 @@ _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); auto __proj = std::__identity(); - return std::__lower_bound_impl<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); + return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); } template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::lower_bound(__first, __last, __value, - __less::value_type, _Tp>()); + return std::lower_bound(__first, __last, __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/make_heap.h b/lib/libcxx/include/__algorithm/make_heap.h index d66cfe2e5f..eaf9259c0b 100644 --- a/lib/libcxx/include/__algorithm/make_heap.h +++ b/lib/libcxx/include/__algorithm/make_heap.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -47,10 +50,11 @@ void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::make_heap(std::move(__first), std::move(__last), - __less::value_type>()); + std::make_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H diff --git a/lib/libcxx/include/__algorithm/make_projected.h b/lib/libcxx/include/__algorithm/make_projected.h index 87d4d59042..ec854763a5 100644 --- a/lib/libcxx/include/__algorithm/make_projected.h +++ b/lib/libcxx/include/__algorithm/make_projected.h @@ -32,13 +32,14 @@ struct _ProjectedPred { _Pred& __pred; // Can be a unary or a binary predicate. _Proj& __proj; - _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {} + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) + : __pred(__pred_arg), __proj(__proj_arg) {} template typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) >::type - _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const { + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_Tp&& __v) const { return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); } @@ -47,7 +48,7 @@ struct _ProjectedPred { decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) >::type - _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const { + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_T1&& __lhs, _T2&& __rhs) const { return std::__invoke(__pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs))); @@ -55,25 +56,12 @@ struct _ProjectedPred { }; -template -struct __can_use_pristine_comp : false_type {}; - -template -struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t< - !is_member_pointer::type>::value && ( -#if _LIBCPP_STD_VER > 17 - is_same::type, identity>::value || -#endif - is_same::type, __identity>::value - ) -> > : true_type {}; - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static -__enable_if_t< - !__can_use_pristine_comp<_Pred, _Proj>::value, - _ProjectedPred<_Pred, _Proj> -> +template >::value && + __is_identity<__decay_t<_Proj> >::value), + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) { return _ProjectedPred<_Pred, _Proj>(__pred, __proj); } @@ -81,28 +69,27 @@ __make_projected(_Pred& __pred, _Proj& __proj) { // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in // the call stack when the comparator is invoked, even in an unoptimized build. -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static -__enable_if_t< - __can_use_pristine_comp<_Pred, _Proj>::value, - _Pred& -> -__make_projected(_Pred& __pred, _Proj&) { +template >::value && + __is_identity<__decay_t<_Proj> >::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) { return __pred; } _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI constexpr static +_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { - if constexpr (same_as, identity> && same_as, identity> && + if constexpr (__is_identity>::value && __is_identity>::value && !is_member_pointer_v>) { // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable // optimizations that rely on the type of the comparator. @@ -121,6 +108,6 @@ decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __p _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H diff --git a/lib/libcxx/include/__algorithm/max.h b/lib/libcxx/include/__algorithm/max.h index a08a3fc59b..5d8e64cfff 100644 --- a/lib/libcxx/include/__algorithm/max.h +++ b/lib/libcxx/include/__algorithm/max.h @@ -28,7 +28,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -max(const _Tp& __a, const _Tp& __b, _Compare __comp) +max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__a, __b) ? __b : __a; } @@ -37,9 +37,9 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -max(const _Tp& __a, const _Tp& __b) +max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return _VSTD::max(__a, __b, __less<_Tp>()); + return _VSTD::max(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { - return *_VSTD::max_element(__t.begin(), __t.end(), __less<_Tp>()); + return *_VSTD::max_element(__t.begin(), __t.end(), __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__algorithm/max_element.h b/lib/libcxx/include/__algorithm/max_element.h index 6ac310619b..8fd52c7772 100644 --- a/lib/libcxx/include/__algorithm/max_element.h +++ b/lib/libcxx/include/__algorithm/max_element.h @@ -24,7 +24,7 @@ template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::max_element requires a ForwardIterator"); if (__first != __last) { @@ -48,8 +48,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::max_element(__first, __last, - __less::value_type>()); + return _VSTD::max_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/merge.h b/lib/libcxx/include/__algorithm/merge.h index e54e430bcb..7ee7aaad71 100644 --- a/lib/libcxx/include/__algorithm/merge.h +++ b/lib/libcxx/include/__algorithm/merge.h @@ -60,9 +60,7 @@ _OutputIterator merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - typedef typename iterator_traits<_InputIterator1>::value_type __v1; - typedef typename iterator_traits<_InputIterator2>::value_type __v2; - return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<__v1, __v2>()); + return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/min.h b/lib/libcxx/include/__algorithm/min.h index 2882485ad7..3c0debd6b0 100644 --- a/lib/libcxx/include/__algorithm/min.h +++ b/lib/libcxx/include/__algorithm/min.h @@ -28,7 +28,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -min(const _Tp& __a, const _Tp& __b, _Compare __comp) +min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? __b : __a; } @@ -37,9 +37,9 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -min(const _Tp& __a, const _Tp& __b) +min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return _VSTD::min(__a, __b, __less<_Tp>()); + return _VSTD::min(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { - return *_VSTD::min_element(__t.begin(), __t.end(), __less<_Tp>()); + return *_VSTD::min_element(__t.begin(), __t.end(), __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__algorithm/min_element.h b/lib/libcxx/include/__algorithm/min_element.h index c0706fe9e4..45f3e85ef9 100644 --- a/lib/libcxx/include/__algorithm/min_element.h +++ b/lib/libcxx/include/__algorithm/min_element.h @@ -22,6 +22,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -49,7 +52,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); @@ -61,10 +64,11 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::min_element(__first, __last, - __less::value_type>()); + return _VSTD::min_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/min_max_result.h b/lib/libcxx/include/__algorithm/min_max_result.h index 4be39992b4..ef2d990380 100644 --- a/lib/libcxx/include/__algorithm/min_max_result.h +++ b/lib/libcxx/include/__algorithm/min_max_result.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -47,7 +47,7 @@ struct min_max_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/minmax.h b/lib/libcxx/include/__algorithm/minmax.h index 6ef0a77708..bdcf57b101 100644 --- a/lib/libcxx/include/__algorithm/minmax.h +++ b/lib/libcxx/include/__algorithm/minmax.h @@ -27,7 +27,7 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair -minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) +minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? pair(__b, __a) : pair(__a, __b); @@ -37,9 +37,9 @@ template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair -minmax(const _Tp& __a, const _Tp& __b) +minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return std::minmax(__a, __b, __less<_Tp>()); + return std::minmax(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t) { - return std::minmax(__t, __less<_Tp>()); + return std::minmax(__t, __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__algorithm/minmax_element.h b/lib/libcxx/include/__algorithm/minmax_element.h index caa963e112..5bcaf8354d 100644 --- a/lib/libcxx/include/__algorithm/minmax_element.h +++ b/lib/libcxx/include/__algorithm/minmax_element.h @@ -12,9 +12,10 @@ #include <__algorithm/comp.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -82,7 +83,7 @@ template _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); @@ -93,7 +94,7 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last) { - return std::minmax_element(__first, __last, __less::value_type>()); + return std::minmax_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/mismatch.h b/lib/libcxx/include/__algorithm/mismatch.h index 600e2cdd3d..e5b014f457 100644 --- a/lib/libcxx/include/__algorithm/mismatch.h +++ b/lib/libcxx/include/__algorithm/mismatch.h @@ -38,7 +38,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY return std::mismatch(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> diff --git a/lib/libcxx/include/__algorithm/move.h b/lib/libcxx/include/__algorithm/move.h index ac95bda7b6..01aeef4e17 100644 --- a/lib/libcxx/include/__algorithm/move.h +++ b/lib/libcxx/include/__algorithm/move.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_MOVE_H #include <__algorithm/copy_move_common.h> +#include <__algorithm/for_each_segment.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> @@ -45,36 +46,34 @@ struct __move_loop { return std::make_pair(std::move(__first), std::move(__result)); } + template + struct _MoveSegment { + using _Traits = __segmented_iterator_traits<_InIter>; + + _OutIter& __result_; + + _LIBCPP_HIDE_FROM_ABI _MoveSegment(_OutIter& __result) : __result_(__result) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { + __result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; + } + }; + template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _InIter __last, _OutIter __result) const { - using _Traits = __segmented_iterator_traits<_InIter>; - auto __sfirst = _Traits::__segment(__first); - auto __slast = _Traits::__segment(__last); - if (__sfirst == __slast) { - auto __iters = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); - return std::make_pair(__last, std::move(__iters.second)); - } - - __result = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - while (__sfirst != __slast) { - __result = - std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - } - __result = - std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result)); return std::make_pair(__last, std::move(__result)); } template ::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; diff --git a/lib/libcxx/include/__algorithm/move_backward.h b/lib/libcxx/include/__algorithm/move_backward.h index d4f013be68..e396abfe0d 100644 --- a/lib/libcxx/include/__algorithm/move_backward.h +++ b/lib/libcxx/include/__algorithm/move_backward.h @@ -76,11 +76,11 @@ struct __move_backward_loop { template ::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; diff --git a/lib/libcxx/include/__algorithm/next_permutation.h b/lib/libcxx/include/__algorithm/next_permutation.h index 73e8b99ab9..d89768ddc1 100644 --- a/lib/libcxx/include/__algorithm/next_permutation.h +++ b/lib/libcxx/include/__algorithm/next_permutation.h @@ -69,8 +69,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) { - return _VSTD::next_permutation(__first, __last, - __less::value_type>()); + return _VSTD::next_permutation(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/nth_element.h b/lib/libcxx/include/__algorithm/nth_element.h index 9fdfb2cae6..dbacf58f9e 100644 --- a/lib/libcxx/include/__algorithm/nth_element.h +++ b/lib/libcxx/include/__algorithm/nth_element.h @@ -14,7 +14,6 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -249,8 +248,7 @@ void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Ra template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) { - std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less::value_type>()); + std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/partial_sort.h b/lib/libcxx/include/__algorithm/partial_sort.h index e0812affe6..56bc9052c7 100644 --- a/lib/libcxx/include/__algorithm/partial_sort.h +++ b/lib/libcxx/include/__algorithm/partial_sort.h @@ -16,11 +16,11 @@ #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -87,8 +87,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { - _VSTD::partial_sort(__first, __middle, __last, - __less::value_type>()); + _VSTD::partial_sort(__first, __middle, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/partial_sort_copy.h b/lib/libcxx/include/__algorithm/partial_sort_copy.h index 1aba07105d..b9635c51d5 100644 --- a/lib/libcxx/include/__algorithm/partial_sort_copy.h +++ b/lib/libcxx/include/__algorithm/partial_sort_copy.h @@ -79,8 +79,7 @@ _RandomAccessIterator partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last) { - return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, - __less::value_type>()); + return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/partition.h b/lib/libcxx/include/__algorithm/partition.h index 0e094bf8dd..a58dd6464a 100644 --- a/lib/libcxx/include/__algorithm/partition.h +++ b/lib/libcxx/include/__algorithm/partition.h @@ -14,7 +14,6 @@ #include <__iterator/iterator_traits.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/pop_heap.h b/lib/libcxx/include/__algorithm/pop_heap.h index 94d32a4239..033af6f2f8 100644 --- a/lib/libcxx/include/__algorithm/pop_heap.h +++ b/lib/libcxx/include/__algorithm/pop_heap.h @@ -17,20 +17,24 @@ #include <__assert> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { - _LIBCPP_ASSERT(__len > 0, "The heap given to pop_heap must be non-empty"); + _LIBCPP_ASSERT_UNCATEGORIZED(__len > 0, "The heap given to pop_heap must be non-empty"); __comp_ref_type<_Compare> __comp_ref = __comp; @@ -64,10 +68,11 @@ void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::pop_heap(std::move(__first), std::move(__last), - __less::value_type>()); + std::pop_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_POP_HEAP_H diff --git a/lib/libcxx/include/__algorithm/prev_permutation.h b/lib/libcxx/include/__algorithm/prev_permutation.h index 0b86ab74ee..187f1e3e5b 100644 --- a/lib/libcxx/include/__algorithm/prev_permutation.h +++ b/lib/libcxx/include/__algorithm/prev_permutation.h @@ -70,8 +70,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) { - return _VSTD::prev_permutation(__first, __last, - __less::value_type>()); + return _VSTD::prev_permutation(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/pstl_any_all_none_of.h b/lib/libcxx/include/__algorithm/pstl_any_all_none_of.h new file mode 100644 index 0000000000..0e50e0ed36 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_any_all_none_of.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_ANY_ALL_NONE_OF_H +#define _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H + +#include <__algorithm/pstl_find.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_any_of(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::find_if(__policy, __g_first, __g_last, __g_pred) != __g_last; + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template +void __pstl_all_of(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { + return !std::any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { + return !__g_pred(__value); + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template +void __pstl_none_of(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { + return !std::any_of(__policy, __g_first, __g_last, __g_pred); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H diff --git a/lib/libcxx/include/__algorithm/pstl_backend.h b/lib/libcxx/include/__algorithm/pstl_backend.h new file mode 100644 index 0000000000..93372f0190 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backend.h @@ -0,0 +1,198 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKEND_H + +#include <__algorithm/pstl_backends/cpu_backend.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +/* +TODO: Documentation of how backends work + +A PSTL parallel backend is a tag type to which the following functions are associated, at minimum: + + template + void __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f); + + template + _Iterator __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template + void __pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp); + + template + _OutIterator __pstl_transform(_InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op); + + template + _OutIterator __pstl_transform(_InIterator1 __first1, + _InIterator1 __last1, + _InIterator2 __first2, + _OutIterator __result, + _BinaryOperation __op); + + template + _Tp __pstl_transform_reduce(_Backend, + _Iterator1 __first1, + _Iterator1 __last1, + _Iterator2 __first2, + _Iterator2 __last2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform); + + template + _Tp __pstl_transform_reduce(_Backend, + _Iterator __first, + _Iterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform); + +// TODO: Complete this list + +The following functions are optional but can be provided. If provided, they are used by the corresponding +algorithms, otherwise they are implemented in terms of other algorithms. If none of the optional algorithms are +implemented, all the algorithms will eventually forward to the basis algorithms listed above: + + template + void __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f); + + template + bool __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template + bool __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template + bool __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template + _Iterator __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template + _Iterator __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template + void __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template + void __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value); + + template + void __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen); + + template + void __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template + void __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen); + + template + _OutIterator __pstl_merge(_Backend, + _Iterator1 __first1, + _Iterator1 __last1, + _Iterator2 __first2, + _Iterator2 __last2, + _OutIterator __result, + _Comp __comp); + + template + _Tp __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op); + + temlate + __iter_value_type<_Iterator> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last); + + template + __iter_diff_t<_Iterator> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template + __iter_diff_t<_Iterator> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template + void __pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value); + + template + void __pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value); + + template + void __pstl_replace_copy(_Backend, + _Iterator __first, + _Iterator __last, + _OutIterator __result, + const _Tp& __old_value, + const _Tp& __new_value); + + template + void __pstl_replace_copy_if(_Backend, + _Iterator __first, + _Iterator __last, + _OutIterator __result, + _Pred __pred, + const _Tp& __new_value); + + template + void __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp); + +// TODO: Complete this list + +*/ + +template +struct __select_backend; + +template <> +struct __select_backend { + using type = __cpu_backend_tag; +}; + +# if _LIBCPP_STD_VER >= 20 +template <> +struct __select_backend { + using type = __cpu_backend_tag; +}; +# endif + +# if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) || \ + defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +template <> +struct __select_backend { + using type = __cpu_backend_tag; +}; + +template <> +struct __select_backend { + using type = __cpu_backend_tag; +}; + +# else + +// ...New vendors can add parallel backends here... + +# error "Invalid choice of a PSTL parallel backend" +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKEND_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backend.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backend.h new file mode 100644 index 0000000000..e54f331b94 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backend.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H + +#include <__config> + +/* + + // _Functor takes a subrange for [__first, __last) that should be executed in serial + template + void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func); + + template + _Tp __parallel_transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction); + + // Cancel the execution of other jobs - they aren't needed anymore + void __cancel_execution(); + + template + void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge); + + template + void __parallel_stable_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Comp __comp, + _LeafSort __leaf_sort); + + TODO: Document the parallel backend +*/ + +#include <__algorithm/pstl_backends/cpu_backends/any_of.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/pstl_backends/cpu_backends/fill.h> +#include <__algorithm/pstl_backends/cpu_backends/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/for_each.h> +#include <__algorithm/pstl_backends/cpu_backends/merge.h> +#include <__algorithm/pstl_backends/cpu_backends/stable_sort.h> +#include <__algorithm/pstl_backends/cpu_backends/transform.h> +#include <__algorithm/pstl_backends/cpu_backends/transform_reduce.h> + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h new file mode 100644 index 0000000000..8fe26797bf --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H + +#include <__algorithm/any_of.h> +#include <__algorithm/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__atomic/atomic.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI bool __parallel_or(_Index __first, _Index __last, _Brick __f) { + std::atomic __found(false); + __par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) { + if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) { + __found.store(true, std::memory_order_relaxed); + __par_backend::__cancel_execution(); + } + }); + return __found; +} + +// TODO: check whether __simd_first() can be used here +template +_LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept { + _DifferenceType __block_size = 4 < __n ? 4 : __n; + const _Index __last = __first + __n; + while (__last != __first) { + int32_t __flag = 1; + _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag) + for (_DifferenceType __i = 0; __i < __block_size; ++__i) + if (__pred(*(__first + __i))) + __flag = 0; + if (!__flag) + return true; + + __first += __block_size; + if (__last - __first >= __block_size << 1) { + // Double the block _Size. Any unnecessary iterations can be amortized against work done so far. + __block_size <<= 1; + } else { + __block_size = __last - __first; + } + } + return false; +} + +template +_LIBCPP_HIDE_FROM_ABI bool +__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return std::__parallel_or( + __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__simd_or(__first, __last - __first, __pred); + } else { + return std::any_of(__first, __last, __pred); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h new file mode 100644 index 0000000000..ea2210a4a7 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H + +#include <__config> +#include + +#if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) +# include <__algorithm/pstl_backends/cpu_backends/serial.h> +#elif defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) +# include <__algorithm/pstl_backends/cpu_backends/thread.h> +#elif defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +# include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> +#else +# error "Invalid CPU backend choice" +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __cpu_backend_tag {}; + +inline constexpr size_t __lane_size = 64; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h new file mode 100644 index 0000000000..5e5e0a23bf --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_FILL_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H + +#include <__algorithm/fill.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n, const _Tp& __value) noexcept { + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __first[__i] = __value; + return __first + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI void +__pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__terminate_on_exception([&] { + __par_backend::__parallel_for( + __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __value); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__simd_fill_n(__first, __last - __first, __value); + } else { + std::fill(__first, __last, __value); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h new file mode 100644 index 0000000000..3fa49549e6 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H + +#include <__algorithm/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _Index +__parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) { + typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + _DifferenceType __initial_dist = __b_first ? __n : -1; + std::atomic<_DifferenceType> __extremum(__initial_dist); + // TODO: find out what is better here: parallel_for or parallel_reduce + __par_backend::__parallel_for(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { + // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of + // why using a shared variable scales fairly well in this situation. + if (__comp(__i - __first, __extremum)) { + _Index __res = __f(__i, __j); + // If not '__last' returned then we found what we want so put this to extremum + if (__res != __j) { + const _DifferenceType __k = __res - __first; + for (_DifferenceType __old = __extremum; __comp(__k, __old); __old = __extremum) { + __extremum.compare_exchange_weak(__old, __k); + } + } + } + }); + return __extremum != __initial_dist ? __first + __extremum : __last; +} + +template +_LIBCPP_HIDE_FROM_ABI _Index +__simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp) noexcept { + // Experiments show good block sizes like this + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__end - __begin >= __block_size) { + _DifferenceType __found = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(| : __found) for (_DifferenceType __i = __begin; __i < __begin + __block_size; ++__i) { + const _DifferenceType __t = __comp(__first, __i); + __lane[__i - __begin] = __t; + __found |= __t; + } + if (__found) { + _DifferenceType __i; + // This will vectorize + for (__i = 0; __i < __block_size; ++__i) { + if (__lane[__i]) { + break; + } + } + return __first + __begin + __i; + } + __begin += __block_size; + } + + // Keep remainder scalar + while (__begin != __end) { + if (__comp(__first, __begin)) { + return __first + __begin; + } + ++__begin; + } + return __first + __end; +} + +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return std::__parallel_find( + __first, + __last, + [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }, + less<>{}, + true); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + using __diff_t = __iter_diff_t<_ForwardIterator>; + return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { + return __pred(__iter[__i]); + }); + } else { + return std::find_if(__first, __last, __pred); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h new file mode 100644 index 0000000000..36d0ac238e --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H + +#include <__algorithm/for_each.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk_1(_Iterator __first, _DifferenceType __n, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first[__i]); + + return __first + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI void +__pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __func); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__simd_walk_1(__first, __last - __first, __func); + } else { + std::for_each(__first, __last, __func); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h new file mode 100644 index 0000000000..bab6a3639b --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H + +#include <__algorithm/lower_bound.h> +#include <__algorithm/max.h> +#include <__algorithm/upper_bound.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__exception/terminate.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/move_iterator.h> +#include <__memory/allocator.h> +#include <__memory/construct_at.h> +#include <__memory/unique_ptr.h> +#include <__numeric/reduce.h> +#include <__utility/exception_guard.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include +#include + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __libdispatch { + +// ::dispatch_apply is marked as __attribute__((nothrow)) because it doesn't let exceptions propagate, and neither do +// we. +// TODO: Do we want to add [[_Clang::__callback__(__func, __context, __)]]? +_LIBCPP_EXPORTED_FROM_ABI void +__dispatch_apply(size_t __chunk_count, void* __context, void (*__func)(void* __context, size_t __chunk)) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI void __dispatch_apply(size_t __chunk_count, _Func __func) noexcept { + __libdispatch::__dispatch_apply(__chunk_count, &__func, [](void* __context, size_t __chunk) { + (*static_cast<_Func*>(__context))(__chunk); + }); +} + +struct __chunk_partitions { + ptrdiff_t __chunk_count_; // includes the first chunk + ptrdiff_t __chunk_size_; + ptrdiff_t __first_chunk_size_; +}; + +[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size); + +template +_LIBCPP_HIDE_FROM_ABI void +__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) { + auto __partitions = __libdispatch::__partition_chunks(__last - __first); + + // Perform the chunked execution. + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = + __chunk == 0 + ? 0 + : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + __func(__first + __index, __first + __index + __this_chunk_size); + }); +} + +template +struct __merge_range { + __merge_range(_RandomAccessIterator1 __mid1, _RandomAccessIterator2 __mid2, _RandomAccessIteratorOut __result) + : __mid1_(__mid1), __mid2_(__mid2), __result_(__result) {} + + _RandomAccessIterator1 __mid1_; + _RandomAccessIterator2 __mid2_; + _RandomAccessIteratorOut __result_; +}; + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + _LeafMerge __leaf_merge) { + __chunk_partitions __partitions = + __libdispatch::__partition_chunks(std::max(__last1 - __first1, __last2 - __first2)); + + if (__partitions.__chunk_count_ == 0) + return; + + if (__partitions.__chunk_count_ == 1) { + __leaf_merge(__first1, __last1, __first2, __last2, __result, __comp); + return; + } + + using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>; + auto const __n_ranges = __partitions.__chunk_count_ + 1; + + // TODO: use __uninitialized_buffer + auto __destroy = [=](__merge_range_t* __ptr) { + std::destroy_n(__ptr, __n_ranges); + std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges); + }; + unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges( + std::allocator<__merge_range_t>().allocate(__n_ranges), __destroy); + + // TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case + std::__terminate_on_exception([&] { + __merge_range_t* __r = __ranges.get(); + std::__construct_at(__r++, __first1, __first2, __result); + + bool __iterate_first_range = __last1 - __first1 > __last2 - __first2; + + auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t { + auto [__mid1, __mid2] = [&] { + if (__iterate_first_range) { + auto __m1 = __first1 + __chunk_size; + auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp); + return std::make_pair(__m1, __m2); + } else { + auto __m2 = __first2 + __chunk_size; + auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp); + return std::make_pair(__m1, __m2); + } + }(); + + __result += (__mid1 - __first1) + (__mid2 - __first2); + __first1 = __mid1; + __first2 = __mid2; + return {std::move(__mid1), std::move(__mid2), __result}; + }; + + // handle first chunk + std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_)); + + // handle 2 -> N - 1 chunks + for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i) + std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_)); + + // handle last chunk + std::__construct_at(__r, __last1, __last2, __result); + + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) { + auto __first_iters = __ranges[__index]; + auto __last_iters = __ranges[__index + 1]; + __leaf_merge( + __first_iters.__mid1_, + __last_iters.__mid1_, + __first_iters.__mid2_, + __last_iters.__mid2_, + __first_iters.__result_, + __comp); + }); + }); +} + +template +_LIBCPP_HIDE_FROM_ABI _Value __parallel_transform_reduce( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Transform __transform, + _Value __init, + _Combiner __combiner, + _Reduction __reduction) { + if (__first == __last) + return __init; + + auto __partitions = __libdispatch::__partition_chunks(__last - __first); + + auto __destroy = [__count = __partitions.__chunk_count_](_Value* __ptr) { + std::destroy_n(__ptr, __count); + std::allocator<_Value>().deallocate(__ptr, __count); + }; + + // TODO: use __uninitialized_buffer + // TODO: allocate one element per worker instead of one element per chunk + unique_ptr<_Value[], decltype(__destroy)> __values( + std::allocator<_Value>().allocate(__partitions.__chunk_count_), __destroy); + + // __dispatch_apply is noexcept + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = + __chunk == 0 + ? 0 + : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + if (__this_chunk_size != 1) { + std::__construct_at( + __values.get() + __chunk, + __reduction(__first + __index + 2, + __first + __index + __this_chunk_size, + __combiner(__transform(__first + __index), __transform(__first + __index + 1)))); + } else { + std::__construct_at(__values.get() + __chunk, __transform(__first + __index)); + } + }); + + return std::__terminate_on_exception([&] { + return std::reduce( + std::make_move_iterator(__values.get()), + std::make_move_iterator(__values.get() + __partitions.__chunk_count_), + std::move(__init), + __combiner); + }); +} + +// TODO: parallelize this +template +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +} // namespace __libdispatch +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h new file mode 100644 index 0000000000..d5be1e302d --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H + +#include <__algorithm/merge.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_merge( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__terminate_on_exception([&] { + __par_backend::__parallel_merge( + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_ForwardIterator1 __g_first1, + _ForwardIterator1 __g_last1, + _ForwardIterator2 __g_first2, + _ForwardIterator2 __g_last2, + _ForwardOutIterator __g_result, + _Comp __g_comp) { + return std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__g_first1), + std::move(__g_last1), + std::move(__g_first2), + std::move(__g_last2), + std::move(__g_result), + std::move(__g_comp)); + }); + return __result + (__last1 - __first1) + (__last2 - __first2); + }); + } else { + return std::merge(__first1, __last1, __first2, __last2, __result, __comp); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h new file mode 100644 index 0000000000..f151c3b098 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h @@ -0,0 +1,72 @@ +// -*- 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_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H + +#include <__config> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __serial_cpu_backend { + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { + __f(__first, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { + return __reduce(std::move(__first), std::move(__last), std::move(__init)); +} + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge) { + __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); +} + +// TODO: Complete this list + +} // namespace __serial_cpu_backend +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h new file mode 100644 index 0000000000..0a701443b3 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/stable_sort.h> +#include <__config> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI void +__pstl_stable_sort(__cpu_backend_tag, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy>) { + std::__terminate_on_exception([&] { + __par_backend::__parallel_stable_sort( + __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__g_first, __g_last, __g_comp); + }); + }); + } else { + std::stable_sort(__first, __last, __comp); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h new file mode 100644 index 0000000000..30eb0ae362 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H + +#include <__assert> +#include <__config> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +// This backend implementation is for testing purposes only and not meant for production use. This will be replaced +// by a proper implementation once the PSTL implementation is somewhat stable. + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __thread_cpu_backend { + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { + __f(__first, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { + return __reduce(std::move(__first), std::move(__last), std::move(__init)); +} + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +template +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge) { + __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); +} + +} // namespace __thread_cpu_backend +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h new file mode 100644 index 0000000000..ef25ff0238 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/transform.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _Iterator2 +__simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i]); + return __first2 + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( + __cpu_backend_tag, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); + }); + }); + return __result + (__last - __first); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__simd_walk_2( + __first, + __last - __first, + __result, + [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { + __out_value = __op(__in_value); + }); + } else { + return std::transform(__first, __last, __result, __op); + } +} + +template +_LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk_3( + _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i], __first3[__i]); + return __first3 + __n; +} +template >, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first1, + __last1, + [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + __brick_last, + __first2 + (__brick_first - __first1), + __result + (__brick_first - __first1), + __op); + }); + }); + return __result + (__last1 - __first1); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__simd_walk_3( + __first1, + __last1 - __first1, + __first2, + __result, + [&](__iter_reference<_ForwardIterator1> __in1, + __iter_reference<_ForwardIterator2> __in2, + __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); + } else { + return std::transform(__first1, __last1, __first2, __result, __op); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H diff --git a/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h new file mode 100644 index 0000000000..c51c312d93 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h @@ -0,0 +1,194 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__numeric/transform_reduce.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/operation_traits.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template < + typename _DifferenceType, + typename _Tp, + typename _BinaryOperation, + typename _UnaryOperation, + __enable_if_t<__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept { + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init) + for (_DifferenceType __i = 0; __i < __n; ++__i) + __init += __f(__i); + return __init; +} + +template < + typename _Size, + typename _Tp, + typename _BinaryOperation, + typename _UnaryOperation, + __enable_if_t::value && is_arithmetic_v<_Tp>), int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept { + const _Size __block_size = __lane_size / sizeof(_Tp); + if (__n > 2 * __block_size && __block_size > 1) { + alignas(__lane_size) char __lane_buffer[__lane_size]; + _Tp* __lane = reinterpret_cast<_Tp*>(__lane_buffer); + + // initializer + _PSTL_PRAGMA_SIMD + for (_Size __i = 0; __i < __block_size; ++__i) { + ::new (__lane + __i) _Tp(__binary_op(__f(__i), __f(__block_size + __i))); + } + // main loop + _Size __i = 2 * __block_size; + const _Size __last_iteration = __block_size * (__n / __block_size); + for (; __i < __last_iteration; __i += __block_size) { + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__i + __j)); + } + } + // remainder + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __n - __last_iteration; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__last_iteration + __j)); + } + // combiner + for (_Size __j = 0; __j < __block_size; ++__j) { + __init = __binary_op(std::move(__init), std::move(__lane[__j])); + } + // destroyer + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j].~_Tp(); + } + } else { + for (_Size __i = 0; __i < __n; ++__i) { + __init = __binary_op(std::move(__init), __f(__i)); + } + } + return __init; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + return std::__terminate_on_exception([&] { + return __par_backend::__parallel_transform_reduce( + __first1, + std::move(__last1), + [__first1, __first2, __transform](_ForwardIterator1 __iter) { + return __transform(*__iter, *(__first2 + (__iter - __first1))); + }, + std::move(__init), + std::move(__reduce), + [__first1, __first2, __reduce, __transform]( + _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + std::move(__brick_last), + __first2 + (__brick_first - __first1), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + return std::__simd_transform_reduce( + __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { + return __transform(__first1[__i], __first2[__i]); + }); + } else { + return std::transform_reduce( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); + } +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( + __cpu_backend_tag, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return __par_backend::__parallel_transform_reduce( + std::move(__first), + std::move(__last), + [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, + std::move(__init), + __reduce, + [__transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__brick_first), + std::move(__brick_last), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__simd_transform_reduce( + __last - __first, + std::move(__init), + std::move(__reduce), + [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); + } else { + return std::transform_reduce( + std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H diff --git a/lib/libcxx/include/__algorithm/pstl_copy.h b/lib/libcxx/include/__algorithm/pstl_copy.h new file mode 100644 index 0000000000..83c712c354 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_copy.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_COPY_H +#define _LIBCPP___ALGORITHM_PSTL_COPY_H + +#include <__algorithm/copy_n.h> +#include <__algorithm/pstl_transform.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// TODO: Use the std::copy/move shenanigans to forward to std::memmove + +template >, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { + return std::transform(__policy, __first, __last, __result, __identity()); +} + +template >, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) + return std::copy(__policy, __first, __first + __n, __result); + else + return std::copy_n(__first, __n, __result); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_COPY_H diff --git a/lib/libcxx/include/__algorithm/pstl_count.h b/lib/libcxx/include/__algorithm/pstl_count.h new file mode 100644 index 0000000000..15acb85de0 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_count.h @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_COUNT_H +#define _LIBCPP___ALGORITHM_PSTL_COUNT_H + +#include <__algorithm/count.h> +#include <__algorithm/for_each.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__numeric/pstl_transform_reduce.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_count_if(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + using __diff_t = __iter_diff_t<_ForwardIterator>; + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count_if), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::transform_reduce( + __policy, + std::move(__g_first), + std::move(__g_last), + __diff_t(), + std::plus{}, + [&](__iter_reference<_ForwardIterator> __element) -> bool { return __g_pred(__element); }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template +void __pstl_count(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + return std::count_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __v) { + return __v == __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_COUNT_H diff --git a/lib/libcxx/include/__algorithm/pstl_fill.h b/lib/libcxx/include/__algorithm/pstl_fill.h new file mode 100644 index 0000000000..d64c828d90 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_fill.h @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_FILL_H +#define _LIBCPP___ALGORITHM_PSTL_FILL_H + +#include <__algorithm/fill_n.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_fill(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +template +void __pstl_fill_n(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n), + [&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) + std::fill(__policy, __g_first, __g_first + __g_n, __g_value); + else + std::fill_n(__g_first, __g_n, __g_value); + }, + std::move(__first), + __n, + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FILL_H diff --git a/lib/libcxx/include/__algorithm/pstl_find.h b/lib/libcxx/include/__algorithm/pstl_find.h new file mode 100644 index 0000000000..8e8adfecfa --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_find.h @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_FIND_H +#define _LIBCPP___ALGORITHM_PSTL_FIND_H + +#include <__algorithm/comp.h> +#include <__algorithm/find.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred)); +} + +template +void __pstl_find_if_not(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { + return !__g_pred(__value); + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template +void __pstl_find(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + return __element == __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FIND_H diff --git a/lib/libcxx/include/__algorithm/pstl_for_each.h b/lib/libcxx/include/__algorithm/pstl_for_each.h new file mode 100644 index 0000000000..09efc24950 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_for_each.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___ALGORITHM_PSTL_FOR_EACH_H +#define _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H + +#include <__algorithm/for_each.h> +#include <__algorithm/for_each_n.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + using _Backend = typename __select_backend<_RawPolicy>::type; + std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func)); +} + +template +void __pstl_for_each_n(); // declaration needed for the frontend dispatch below + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n), + [&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { + std::for_each(__policy, std::move(__g_first), __g_first + __g_size, std::move(__g_func)); + } else { + std::for_each_n(std::move(__g_first), __g_size, std::move(__g_func)); + } + }, + __first, + __size, + std::move(__func)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H diff --git a/lib/libcxx/include/__algorithm/pstl_frontend_dispatch.h b/lib/libcxx/include/__algorithm/pstl_frontend_dispatch.h new file mode 100644 index 0000000000..dc49f3e516 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_frontend_dispatch.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_FRONTEND_DISPATCH +#define _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH + +#include <__config> +#include <__type_traits/is_callable.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +# define _LIBCPP_PSTL_CUSTOMIZATION_POINT(name) \ + [](auto&&... __args) -> decltype(std::name<_RawPolicy>(typename __select_backend<_RawPolicy>::type{}, \ + std::forward(__args)...)) { \ + return std::name<_RawPolicy>( \ + typename __select_backend<_RawPolicy>::type{}, std::forward(__args)...); \ + } + +template +_LIBCPP_HIDE_FROM_ABI decltype(auto) +__pstl_frontend_dispatch(_SpecializedImpl __specialized_impl, _GenericImpl __generic_impl, _Args&&... __args) { + if constexpr (__is_callable<_SpecializedImpl, _Args...>::value) { + return __specialized_impl(std::forward<_Args>(__args)...); + } else { + return __generic_impl(std::forward<_Args>(__args)...); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH diff --git a/lib/libcxx/include/__algorithm/pstl_generate.h b/lib/libcxx/include/__algorithm/pstl_generate.h new file mode 100644 index 0000000000..e1ba0183dc --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_generate.h @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_GENERATE_H +#define _LIBCPP___ALGORITHM_PSTL_GENERATE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_generate(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Generator __g_gen) { + std::for_each( + __policy, std::move(__g_first), std::move(__g_last), [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_gen(); + }); + }, + std::move(__first), + std::move(__last), + std::move(__gen)); +} + +template +void __pstl_generate_n(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate_n), + [&__policy](_ForwardIterator __g_first, _Size __g_n, _Generator __g_gen) { + std::for_each_n(__policy, std::move(__g_first), __g_n, [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_gen(); + }); + }, + std::move(__first), + __n, + std::move(__gen)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_GENERATE_H diff --git a/lib/libcxx/include/__algorithm/pstl_is_partitioned.h b/lib/libcxx/include/__algorithm/pstl_is_partitioned.h new file mode 100644 index 0000000000..6f6e9b2f44 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_is_partitioned.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_IS_PARITTIONED +#define _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED + +#include <__algorithm/pstl_any_all_none_of.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_find.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_is_partitioned(); + +template , + enable_if_t, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_is_partitioned), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + __g_first = std::find_if_not(__policy, __g_first, __g_last, __g_pred); + if (__g_first == __g_last) + return true; + ++__g_first; + return std::none_of(__policy, __g_first, __g_last, __g_pred); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED diff --git a/lib/libcxx/include/__algorithm/pstl_merge.h b/lib/libcxx/include/__algorithm/pstl_merge.h new file mode 100644 index 0000000000..f10ac76742 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_merge.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_MERGE_H +#define _LIBCPP___ALGORITHM_PSTL_MERGE_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +merge(_ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp = {}) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_merge<_RawPolicy>( + _Backend{}, + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + std::move(__comp)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_MERGE_H diff --git a/lib/libcxx/include/__algorithm/pstl_replace.h b/lib/libcxx/include/__algorithm/pstl_replace.h new file mode 100644 index 0000000000..04ffaaba59 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_replace.h @@ -0,0 +1,167 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_REPLACE_H +#define _LIBCPP___ALGORITHM_PSTL_REPLACE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__algorithm/pstl_transform.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_replace_if(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace_if(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Pred __pred, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred, const _Tp& __g_new_value) { + std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + if (__g_pred(__element)) + __element = __g_new_value; + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred), + __new_value); +} + +template +void __pstl_replace(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + const _Tp& __old_value, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace), + [&__policy]( + _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) { + std::replace_if( + __policy, + std::move(__g_first), + std::move(__g_last), + [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, + __g_new_value); + }, + std::move(__first), + std::move(__last), + __old_value, + __new_value); +} + +template +void __pstl_replace_copy_if(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy_if( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _Pred __pred, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if), + [&__policy](_ForwardIterator __g_first, + _ForwardIterator __g_last, + _ForwardOutIterator __g_result, + _Pred __g_pred, + const _Tp& __g_new_value) { + std::transform(__policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) { + return __g_pred(__element) ? __g_new_value : __element; + }); + }, + std::move(__first), + std::move(__last), + std::move(__result), + std::move(__pred), + __new_value); +} + +template +void __pstl_replace_copy(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + const _Tp& __old_value, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy), + [&__policy](_ForwardIterator __g_first, + _ForwardIterator __g_last, + _ForwardOutIterator __g_result, + const _Tp& __g_old_value, + const _Tp& __g_new_value) { + return std::replace_copy_if( + __policy, + std::move(__g_first), + std::move(__g_last), + std::move(__g_result), + [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, + __g_new_value); + }, + std::move(__first), + std::move(__last), + std::move(__result), + __old_value, + __new_value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H diff --git a/lib/libcxx/include/__algorithm/pstl_sort.h b/lib/libcxx/include/__algorithm/pstl_sort.h new file mode 100644 index 0000000000..75c77ed405 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_sort.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_PSTL_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_SORT_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__algorithm/pstl_stable_sort.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_sort(); + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_sort), + [&__policy](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__policy, std::move(__g_first), std::move(__g_last), std::move(__g_comp)); + }, + std::move(__first), + std::move(__last), + std::move(__comp)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last) { + std::sort(std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{}); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_SORT_H diff --git a/lib/libcxx/include/__algorithm/pstl_stable_sort.h b/lib/libcxx/include/__algorithm/pstl_stable_sort.h new file mode 100644 index 0000000000..510ffd8629 --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_stable_sort.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp = {}) { + using _Backend = typename __select_backend<_RawPolicy>::type; + std::__pstl_stable_sort<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__comp)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H diff --git a/lib/libcxx/include/__algorithm/pstl_transform.h b/lib/libcxx/include/__algorithm/pstl_transform.h new file mode 100644 index 0000000000..27d95349fc --- /dev/null +++ b/lib/libcxx/include/__algorithm/pstl_transform.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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_PSTL_TRANSFORM_H +#define _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first))); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform<_RawPolicy>( + _Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2))); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform<_RawPolicy>( + _Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H diff --git a/lib/libcxx/include/__algorithm/push_heap.h b/lib/libcxx/include/__algorithm/push_heap.h index 9068495774..82b571e44b 100644 --- a/lib/libcxx/include/__algorithm/push_heap.h +++ b/lib/libcxx/include/__algorithm/push_heap.h @@ -14,13 +14,17 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -68,10 +72,11 @@ void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::push_heap(std::move(__first), std::move(__last), - __less::value_type>()); + std::push_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_PUSH_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_adjacent_find.h b/lib/libcxx/include/__algorithm/ranges_adjacent_find.h index d338d13e6e..5f33192666 100644 --- a/lib/libcxx/include/__algorithm/ranges_adjacent_find.h +++ b/lib/libcxx/include/__algorithm/ranges_adjacent_find.h @@ -24,17 +24,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __adjacent_find { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { if (__first == __last) return __first; @@ -47,32 +46,33 @@ struct __fn { return __i; } - template _Sent, - class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_binary_predicate, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); } template , _Proj>, - projected, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { + indirect_binary_predicate, _Proj>, projected, _Proj>> + _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __adjacent_find inline namespace __cpo { - inline constexpr auto adjacent_find = __adjacent_find::__fn{}; +inline constexpr auto adjacent_find = __adjacent_find::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H diff --git a/lib/libcxx/include/__algorithm/ranges_all_of.h b/lib/libcxx/include/__algorithm/ranges_all_of.h index e45c4e5843..39a2ae4de0 100644 --- a/lib/libcxx/include/__algorithm/ranges_all_of.h +++ b/lib/libcxx/include/__algorithm/ranges_all_of.h @@ -22,17 +22,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __all_of { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (!std::invoke(__pred, std::invoke(__proj, *__first))) return false; @@ -40,29 +38,32 @@ struct __fn { return true; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __all_of inline namespace __cpo { - inline constexpr auto all_of = __all_of::__fn{}; +inline constexpr auto all_of = __all_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ALL_OF_H diff --git a/lib/libcxx/include/__algorithm/ranges_any_of.h b/lib/libcxx/include/__algorithm/ranges_any_of.h index e7d1e723a7..2ca8531102 100644 --- a/lib/libcxx/include/__algorithm/ranges_any_of.h +++ b/lib/libcxx/include/__algorithm/ranges_any_of.h @@ -22,17 +22,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __any_of { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) return true; @@ -40,29 +38,32 @@ struct __fn { return false; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __any_of inline namespace __cpo { - inline constexpr auto any_of = __any_of::__fn{}; +inline constexpr auto any_of = __any_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ANY_OF_H diff --git a/lib/libcxx/include/__algorithm/ranges_binary_search.h b/lib/libcxx/include/__algorithm/ranges_binary_search.h index d72d4e0574..22008e0f1b 100644 --- a/lib/libcxx/include/__algorithm/ranges_binary_search.h +++ b/lib/libcxx/include/__algorithm/ranges_binary_search.h @@ -24,40 +24,45 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __binary_search { struct __fn { - template _Sent, class _Type, class _Proj = identity, + template _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + auto __last = ranges::end(__r); + auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } }; } // namespace __binary_search inline namespace __cpo { - inline constexpr auto binary_search = __binary_search::__fn{}; +inline constexpr auto binary_search = __binary_search::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H diff --git a/lib/libcxx/include/__algorithm/ranges_clamp.h b/lib/libcxx/include/__algorithm/ranges_clamp.h index 09a97fc790..9613f7f377 100644 --- a/lib/libcxx/include/__algorithm/ranges_clamp.h +++ b/lib/libcxx/include/__algorithm/ranges_clamp.h @@ -22,25 +22,20 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __clamp { struct __fn { - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Type& operator()(const _Type& __value, - const _Type& __low, - const _Type& __high, - _Comp __comp = {}, - _Proj __proj = {}) const { - _LIBCPP_ASSERT(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), - "Bad bounds passed to std::ranges::clamp"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( + const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), + "Bad bounds passed to std::ranges::clamp"); if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) return __low; @@ -49,17 +44,16 @@ struct __fn { else return __value; } - }; } // namespace __clamp inline namespace __cpo { - inline constexpr auto clamp = __clamp::__fn{}; +inline constexpr auto clamp = __clamp::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H diff --git a/lib/libcxx/include/__algorithm/ranges_copy.h b/lib/libcxx/include/__algorithm/ranges_copy.h index bb02c84efb..1c87f074e7 100644 --- a/lib/libcxx/include/__algorithm/ranges_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_copy.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,19 +36,18 @@ using copy_result = in_out_result<_InIter, _OutIter>; namespace __copy { struct __fn { - template _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_result, _OutIter> operator()(_Range&& __r, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_result, _OutIter> + operator()(_Range&& __r, _OutIter __result) const { auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -56,12 +55,12 @@ struct __fn { } // namespace __copy inline namespace __cpo { - inline constexpr auto copy = __copy::__fn{}; +inline constexpr auto copy = __copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_copy_backward.h b/lib/libcxx/include/__algorithm/ranges_copy_backward.h index f41af66f39..865e944d43 100644 --- a/lib/libcxx/include/__algorithm/ranges_copy_backward.h +++ b/lib/libcxx/include/__algorithm/ranges_copy_backward.h @@ -23,30 +23,29 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template +template using copy_backward_result = in_out_result<_Ip, _Op>; namespace __copy_backward { struct __fn { - template _Sent1, bidirectional_iterator _InIter2> requires indirectly_copyable<_InIter1, _InIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_backward_result<_InIter1, _InIter2> operator()(_InIter1 __first, _Sent1 __last, _InIter2 __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_backward_result<_InIter1, _InIter2> + operator()(_InIter1 __first, _Sent1 __last, _InIter2 __result) const { auto __ret = std::__copy_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template requires indirectly_copyable, _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_backward_result, _Iter> operator()(_Range&& __r, _Iter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const { auto __ret = std::__copy_backward<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -54,12 +53,12 @@ struct __fn { } // namespace __copy_backward inline namespace __cpo { - inline constexpr auto copy_backward = __copy_backward::__fn{}; +inline constexpr auto copy_backward = __copy_backward::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H diff --git a/lib/libcxx/include/__algorithm/ranges_copy_if.h b/lib/libcxx/include/__algorithm/ranges_copy_if.h index dba41c3b3a..b77dbd37fc 100644 --- a/lib/libcxx/include/__algorithm/ranges_copy_if.h +++ b/lib/libcxx/include/__algorithm/ranges_copy_if.h @@ -24,21 +24,19 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template +template using copy_if_result = in_out_result<_Ip, _Op>; namespace __copy_if { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI static constexpr - copy_if_result <_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI static constexpr copy_if_result<_InIter, _OutIter> __copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) { @@ -49,20 +47,23 @@ struct __fn { return {std::move(__first), std::move(__result)}; } - template _Sent, weakly_incrementable _OutIter, class _Proj = identity, + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, indirect_unary_predicate> _Pred> requires indirectly_copyable<_Iter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_if_result<_Iter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<_Iter, _OutIter> operator()(_Iter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { return __copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); } - template , _Proj>> _Pred> requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_if_result, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr copy_if_result, _OutIter> operator()(_Range&& __r, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { return __copy_if_impl(ranges::begin(__r), ranges::end(__r), std::move(__result), __pred, __proj); } @@ -70,12 +71,12 @@ struct __fn { } // namespace __copy_if inline namespace __cpo { - inline constexpr auto copy_if = __copy_if::__fn{}; +inline constexpr auto copy_if = __copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_copy_n.h b/lib/libcxx/include/__algorithm/ranges_copy_n.h index 04bb80b3ba..99e8eee14d 100644 --- a/lib/libcxx/include/__algorithm/ranges_copy_n.h +++ b/lib/libcxx/include/__algorithm/ranges_copy_n.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -36,10 +36,9 @@ using copy_n_result = in_out_result<_Ip, _Op>; namespace __copy_n { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> + __go(_InIter __first, _DiffType __n, _OutIter __result) { while (__n != 0) { *__result = *__first; ++__first; @@ -50,27 +49,27 @@ struct __fn { } template - _LIBCPP_HIDE_FROM_ABI constexpr static - copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> + __go(_InIter __first, _DiffType __n, _OutIter __result) { auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result); return {__ret.first, __ret.second}; } template requires indirectly_copyable<_Ip, _Op> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_n_result<_Ip, _Op> operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op> + operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { return __go(std::move(__first), __n, std::move(__result)); } }; } // namespace __copy_n inline namespace __cpo { - inline constexpr auto copy_n = __copy_n::__fn{}; +inline constexpr auto copy_n = __copy_n::__fn{}; } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/ranges_count.h b/lib/libcxx/include/__algorithm/ranges_count.h index 527dd06200..82f5456756 100644 --- a/lib/libcxx/include/__algorithm/ranges_count.h +++ b/lib/libcxx/include/__algorithm/ranges_count.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,16 +34,16 @@ namespace __count { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __e) { return __e == __value; }; return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __e) { return __e == __value; }; return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } @@ -51,12 +51,12 @@ struct __fn { } // namespace __count inline namespace __cpo { - inline constexpr auto count = __count::__fn{}; +inline constexpr auto count = __count::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COUNT_H diff --git a/lib/libcxx/include/__algorithm/ranges_count_if.h b/lib/libcxx/include/__algorithm/ranges_count_if.h index 931618b7b5..92f37d049e 100644 --- a/lib/libcxx/include/__algorithm/ranges_count_if.h +++ b/lib/libcxx/include/__algorithm/ranges_count_if.h @@ -25,15 +25,14 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI constexpr -iter_difference_t<_Iter> __count_if_impl(_Iter __first, _Sent __last, - _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> +__count_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { iter_difference_t<_Iter> __counter(0); for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) @@ -44,29 +43,32 @@ iter_difference_t<_Iter> __count_if_impl(_Iter __first, _Sent __last, namespace __count_if { struct __fn { - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } }; } // namespace __count_if inline namespace __cpo { - inline constexpr auto count_if = __count_if::__fn{}; +inline constexpr auto count_if = __count_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_equal.h b/lib/libcxx/include/__algorithm/ranges_equal.h index 3c417f09de..4cb1f7df19 100644 --- a/lib/libcxx/include/__algorithm/ranges_equal.h +++ b/lib/libcxx/include/__algorithm/ranges_equal.h @@ -9,6 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_EQUAL_H #define _LIBCPP___ALGORITHM_RANGES_EQUAL_H +#include <__algorithm/equal.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -24,92 +26,79 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __equal { struct __fn { -private: - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __equal_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, - _Proj1& __proj1, - _Proj2& __proj2) { - while (__first1 != __last1 && __first2 != __last2) { - if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) - return false; - ++__first1; - ++__first2; - } - return __first1 == __last1 && __first2 == __last2; - } - -public: - - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) { if (__last1 - __first1 != __last2 - __first2) return false; } - return __equal_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __pred, - __proj1, - __proj2); + auto __unwrapped1 = std::__unwrap_range(std::move(__first1), std::move(__last1)); + auto __unwrapped2 = std::__unwrap_range(std::move(__first2), std::move(__last2)); + return std::__equal_impl( + std::move(__unwrapped1.first), + std::move(__unwrapped1.second), + std::move(__unwrapped2.first), + std::move(__unwrapped2.second), + __pred, + __proj1, + __proj2); } template requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) return false; } - return __equal_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __pred, - __proj1, - __proj2); + auto __unwrapped1 = std::__unwrap_range(ranges::begin(__range1), ranges::end(__range1)); + auto __unwrapped2 = std::__unwrap_range(ranges::begin(__range2), ranges::end(__range2)); + return std::__equal_impl( + std::move(__unwrapped1.first), + std::move(__unwrapped1.second), + std::move(__unwrapped2.first), + std::move(__unwrapped2.second), + __pred, + __proj1, + __proj2); return false; } }; } // namespace __equal inline namespace __cpo { - inline constexpr auto equal = __equal::__fn{}; +inline constexpr auto equal = __equal::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_H diff --git a/lib/libcxx/include/__algorithm/ranges_equal_range.h b/lib/libcxx/include/__algorithm/ranges_equal_range.h index 94dc058e7b..ed78cf312c 100644 --- a/lib/libcxx/include/__algorithm/ranges_equal_range.h +++ b/lib/libcxx/include/__algorithm/ranges_equal_range.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,28 +38,25 @@ namespace ranges { namespace __equal_range { struct __fn { - template < - forward_iterator _Iter, - sentinel_for<_Iter> _Sent, - class _Tp, - class _Proj = identity, - indirect_strict_weak_order> _Comp = ranges::less> + template _Sent, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__equal_range<_RangeAlgPolicy>( - std::move(__first), std::move(__last), __value, __comp, __proj); + auto __ret = std::__equal_range<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } - template < - forward_range _Range, - class _Tp, - class _Proj = identity, - indirect_strict_weak_order, _Proj>> _Comp = ranges::less> + template , _Proj>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__equal_range<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); + auto __ret = + std::__equal_range<_RangeAlgPolicy>(ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } }; @@ -67,12 +64,12 @@ struct __fn { } // namespace __equal_range inline namespace __cpo { - inline constexpr auto equal_range = __equal_range::__fn{}; +inline constexpr auto equal_range = __equal_range::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H diff --git a/lib/libcxx/include/__algorithm/ranges_fill.h b/lib/libcxx/include/__algorithm/ranges_fill.h index 6ebc2bd67d..88a892f5c2 100644 --- a/lib/libcxx/include/__algorithm/ranges_fill.h +++ b/lib/libcxx/include/__algorithm/ranges_fill.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -28,9 +28,8 @@ namespace ranges { namespace __fill { struct __fn { template _Iter, sentinel_for<_Iter> _Sent> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { - if constexpr(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { + if constexpr (random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { return ranges::fill_n(__first, __last - __first, __value); } else { for (; __first != __last; ++__first) @@ -40,20 +39,19 @@ struct __fn { } template _Range> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type& __value) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type& __value) const { return (*this)(ranges::begin(__range), ranges::end(__range), __value); } }; } // namespace __fill inline namespace __cpo { - inline constexpr auto fill = __fill::__fn{}; +inline constexpr auto fill = __fill::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FILL_H diff --git a/lib/libcxx/include/__algorithm/ranges_fill_n.h b/lib/libcxx/include/__algorithm/ranges_fill_n.h index a2660e8b59..dbd8ec27ae 100644 --- a/lib/libcxx/include/__algorithm/ranges_fill_n.h +++ b/lib/libcxx/include/__algorithm/ranges_fill_n.h @@ -17,7 +17,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -25,8 +25,8 @@ namespace ranges { namespace __fill_n { struct __fn { template _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Type& __value) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Type& __value) const { for (; __n != 0; --__n) { *__first = __value; ++__first; @@ -37,12 +37,12 @@ struct __fn { } // namespace __fill_n inline namespace __cpo { - inline constexpr auto fill_n = __fill_n::__fn{}; +inline constexpr auto fill_n = __fill_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FILL_N_H diff --git a/lib/libcxx/include/__algorithm/ranges_find.h b/lib/libcxx/include/__algorithm/ranges_find.h index 580c2a14c9..de870e3811 100644 --- a/lib/libcxx/include/__algorithm/ranges_find.h +++ b/lib/libcxx/include/__algorithm/ranges_find.h @@ -9,7 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FIND_H #define _LIBCPP___ALGORITHM_RANGES_FIND_H +#include <__algorithm/find.h> #include <__algorithm/ranges_find_if.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -26,38 +28,48 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find { struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr _Iter + __find_unwrap(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { + if constexpr (forward_iterator<_Iter>) { + auto [__first_un, __last_un] = std::__unwrap_range(__first, std::move(__last)); + return std::__rewrap_range<_Sent>( + std::move(__first), std::__find_impl(std::move(__first_un), std::move(__last_un), __value, __proj)); + } else { + return std::__find_impl(std::move(__first), std::move(__last), __value, __proj); + } + } + template _Sp, class _Tp, class _Proj = identity> requires indirect_binary_predicate, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __e) { return std::forward(__e) == __value; }; - return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { + return __find_unwrap(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __e) { return std::forward(__e) == __value; }; - return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { + return __find_unwrap(ranges::begin(__r), ranges::end(__r), __value, __proj); } }; } // namespace __find inline namespace __cpo { - inline constexpr auto find = __find::__fn{}; +inline constexpr auto find = __find::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_H diff --git a/lib/libcxx/include/__algorithm/ranges_find_end.h b/lib/libcxx/include/__algorithm/ranges_find_end.h index ea36f4d4e6..2c57ad424b 100644 --- a/lib/libcxx/include/__algorithm/ranges_find_end.h +++ b/lib/libcxx/include/__algorithm/ranges_find_end.h @@ -27,25 +27,29 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_end { struct __fn { - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( __first1, __last1, @@ -61,16 +65,12 @@ struct __fn { template requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -87,12 +87,12 @@ struct __fn { } // namespace __find_end inline namespace __cpo { - inline constexpr auto find_end = __find_end::__fn{}; +inline constexpr auto find_end = __find_end::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_END_H diff --git a/lib/libcxx/include/__algorithm/ranges_find_first_of.h b/lib/libcxx/include/__algorithm/ranges_find_first_of.h index 9d66e7511c..ec6d52c632 100644 --- a/lib/libcxx/include/__algorithm/ranges_find_first_of.h +++ b/lib/libcxx/include/__algorithm/ranges_find_first_of.h @@ -24,21 +24,22 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_first_of { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter1 __find_first_of_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, - _Proj1& __proj1, - _Proj2& __proj2) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter1 __find_first_of_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { for (; __first1 != __last1; ++__first1) { for (auto __j = __first2; __j != __last2; ++__j) { if (std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__j))) @@ -48,54 +49,53 @@ struct __fn { return __first1; } - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter1 operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __find_first_of_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __pred, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __find_first_of_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } template requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __find_first_of_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __pred, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __find_first_of_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2); } - }; } // namespace __find_first_of inline namespace __cpo { - inline constexpr auto find_first_of = __find_first_of::__fn{}; +inline constexpr auto find_first_of = __find_first_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H diff --git a/lib/libcxx/include/__algorithm/ranges_find_if.h b/lib/libcxx/include/__algorithm/ranges_find_if.h index 45ce6e460d..af54a5007e 100644 --- a/lib/libcxx/include/__algorithm/ranges_find_if.h +++ b/lib/libcxx/include/__algorithm/ranges_find_if.h @@ -24,15 +24,14 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI static constexpr -_Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) break; @@ -42,30 +41,30 @@ _Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { namespace __find_if { struct __fn { - - template _Sp, class _Proj = identity, + template _Sp, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } }; } // namespace __find_if inline namespace __cpo { - inline constexpr auto find_if = __find_if::__fn{}; +inline constexpr auto find_if = __find_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_find_if_not.h b/lib/libcxx/include/__algorithm/ranges_find_if_not.h index 3dd1213275..6beade1462 100644 --- a/lib/libcxx/include/__algorithm/ranges_find_if_not.h +++ b/lib/libcxx/include/__algorithm/ranges_find_if_not.h @@ -26,25 +26,26 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_if_not { struct __fn { - template _Sp, class _Proj = identity, + template _Sp, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); } - template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + template , _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); } @@ -52,12 +53,12 @@ struct __fn { } // namespace __find_if_not inline namespace __cpo { - inline constexpr auto find_if_not = __find_if_not::__fn{}; +inline constexpr auto find_if_not = __find_if_not::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H diff --git a/lib/libcxx/include/__algorithm/ranges_for_each.h b/lib/libcxx/include/__algorithm/ranges_for_each.h index 0c70c05981..7878ed2670 100644 --- a/lib/libcxx/include/__algorithm/ranges_for_each.h +++ b/lib/libcxx/include/__algorithm/ranges_for_each.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,42 +37,40 @@ namespace __for_each { struct __fn { private: template - _LIBCPP_HIDE_FROM_ABI constexpr static - for_each_result<_Iter, _Func> __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { + _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)}; } public: - template _Sent, + template _Sent, class _Proj = identity, indirectly_unary_invocable> _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - for_each_result<_Iter, _Func> operator()(_Iter __first, _Sent __last, _Func __func, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr for_each_result<_Iter, _Func> + operator()(_Iter __first, _Sent __last, _Func __func, _Proj __proj = {}) const { return __for_each_impl(std::move(__first), std::move(__last), __func, __proj); } template , _Proj>> _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - for_each_result, _Func> operator()(_Range&& __range, - _Func __func, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr for_each_result, _Func> + operator()(_Range&& __range, _Func __func, _Proj __proj = {}) const { return __for_each_impl(ranges::begin(__range), ranges::end(__range), __func, __proj); } - }; } // namespace __for_each inline namespace __cpo { - inline constexpr auto for_each = __for_each::__fn{}; +inline constexpr auto for_each = __for_each::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H diff --git a/lib/libcxx/include/__algorithm/ranges_for_each_n.h b/lib/libcxx/include/__algorithm/ranges_for_each_n.h index 261816aba4..53ccb9a603 100644 --- a/lib/libcxx/include/__algorithm/ranges_for_each_n.h +++ b/lib/libcxx/include/__algorithm/ranges_for_each_n.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,32 +35,25 @@ using for_each_n_result = in_fun_result<_Iter, _Func>; namespace __for_each_n { struct __fn { - - 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 { + 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)}; } - }; } // namespace __for_each_n inline namespace __cpo { - inline constexpr auto for_each_n = __for_each_n::__fn{}; +inline constexpr auto for_each_n = __for_each_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H diff --git a/lib/libcxx/include/__algorithm/ranges_generate.h b/lib/libcxx/include/__algorithm/ranges_generate.h index ae486ae653..3ff1e13c42 100644 --- a/lib/libcxx/include/__algorithm/ranges_generate.h +++ b/lib/libcxx/include/__algorithm/ranges_generate.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,10 +32,8 @@ namespace ranges { namespace __generate { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr - static _OutIter __generate_fn_impl(_OutIter __first, _Sent __last, _Func& __gen) { + _LIBCPP_HIDE_FROM_ABI constexpr static _OutIter __generate_fn_impl(_OutIter __first, _Sent __last, _Func& __gen) { for (; __first != __last; ++__first) { *__first = __gen(); } @@ -44,30 +42,27 @@ struct __fn { } template _Sent, copy_constructible _Func> - requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - _OutIter operator()(_OutIter __first, _Sent __last, _Func __gen) const { + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr _OutIter operator()(_OutIter __first, _Sent __last, _Func __gen) const { return __generate_fn_impl(std::move(__first), std::move(__last), __gen); } template - requires invocable<_Func&> && output_range<_Range, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Func __gen) const { + requires invocable<_Func&> && output_range<_Range, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Func __gen) const { return __generate_fn_impl(ranges::begin(__range), ranges::end(__range), __gen); } - }; } // namespace __generate inline namespace __cpo { - inline constexpr auto generate = __generate::__fn{}; +inline constexpr auto generate = __generate::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_H diff --git a/lib/libcxx/include/__algorithm/ranges_generate_n.h b/lib/libcxx/include/__algorithm/ranges_generate_n.h index e625e3a974..c025c621a1 100644 --- a/lib/libcxx/include/__algorithm/ranges_generate_n.h +++ b/lib/libcxx/include/__algorithm/ranges_generate_n.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,11 +33,10 @@ namespace ranges { namespace __generate_n { struct __fn { - template - requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - _OutIter operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr _OutIter + operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { for (; __n > 0; --__n) { *__first = __gen(); ++__first; @@ -45,18 +44,17 @@ struct __fn { return __first; } - }; } // namespace __generate_n inline namespace __cpo { - inline constexpr auto generate_n = __generate_n::__fn{}; +inline constexpr auto generate_n = __generate_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H diff --git a/lib/libcxx/include/__algorithm/ranges_includes.h b/lib/libcxx/include/__algorithm/ranges_includes.h index 8438117cfa..aa35080c8c 100644 --- a/lib/libcxx/include/__algorithm/ranges_includes.h +++ b/lib/libcxx/include/__algorithm/ranges_includes.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,14 +35,13 @@ namespace ranges { namespace __includes { struct __fn { - template < - input_iterator _Iter1, - sentinel_for<_Iter1> _Sent1, - input_iterator _Iter2, - sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> + template _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, @@ -61,13 +60,12 @@ struct __fn { std::move(__proj2)); } - template < - input_range _Range1, - input_range _Range2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_strict_weak_order, _Proj1>, projected, _Proj2>> - _Comp = ranges::less> + template , _Proj1>, projected, _Proj2>> + _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return std::__includes( @@ -84,12 +82,12 @@ struct __fn { } // namespace __includes inline namespace __cpo { - inline constexpr auto includes = __includes::__fn{}; +inline constexpr auto includes = __includes::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_INCLUDES_H diff --git a/lib/libcxx/include/__algorithm/ranges_inplace_merge.h b/lib/libcxx/include/__algorithm/ranges_inplace_merge.h index 88171a65c8..86001b003d 100644 --- a/lib/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/lib/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -31,55 +31,49 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __inplace_merge { - struct __fn { - template - _LIBCPP_HIDE_FROM_ABI static constexpr 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>( - std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); - return __last_iter; - } +struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr 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>( + std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); + return __last_iter; + } - template < - bidirectional_iterator _Iter, - sentinel_for<_Iter> _Sent, - class _Comp = ranges::less, - class _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI _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)); - } + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI _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)); + } - template - requires sortable< - iterator_t<_Range>, - _Comp, - _Proj> _LIBCPP_HIDE_FROM_ABI 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)); - } - }; + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI 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)); + } +}; } // namespace __inplace_merge inline namespace __cpo { - inline constexpr auto inplace_merge = __inplace_merge::__fn{}; +inline constexpr auto inplace_merge = __inplace_merge::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_heap.h b/lib/libcxx/include/__algorithm/ranges_is_heap.h index a16c075b07..f298c347b7 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_heap.h +++ b/lib/libcxx/include/__algorithm/ranges_is_heap.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,28 +34,30 @@ namespace ranges { namespace __is_heap { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr - static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { - auto __last_iter = ranges::next(__first, __last); + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __is_heap_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); auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); return __result == __last; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } }; @@ -63,12 +65,12 @@ struct __fn { } // namespace __is_heap inline namespace __cpo { - inline constexpr auto is_heap = __is_heap::__fn{}; +inline constexpr auto is_heap = __is_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_heap_until.h b/lib/libcxx/include/__algorithm/ranges_is_heap_until.h index 8c8dac5bc9..73f13fb504 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_heap_until.h +++ b/lib/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,41 +35,42 @@ namespace ranges { namespace __is_heap_until { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr - static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { - auto __last_iter = ranges::next(__first, __last); + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __is_heap_until_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); return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } - }; } // namespace __is_heap_until inline namespace __cpo { - inline constexpr auto is_heap_until = __is_heap_until::__fn{}; +inline constexpr auto is_heap_until = __is_heap_until::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_partitioned.h b/lib/libcxx/include/__algorithm/ranges_is_partitioned.h index b903953d61..76db870efc 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_partitioned.h +++ b/lib/libcxx/include/__algorithm/ranges_is_partitioned.h @@ -23,17 +23,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_partitioned { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __is_parititioned_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __is_partitioned_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (!std::invoke(__pred, std::invoke(__proj, *__first))) break; @@ -51,31 +50,32 @@ struct __fn { return true; } - template _Sent, + template _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - return __is_parititioned_impl(std::move(__first), std::move(__last), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __is_partitioned_impl(std::move(__first), std::move(__last), __pred, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { - return __is_parititioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __is_partitioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __is_partitioned inline namespace __cpo { - inline constexpr auto is_partitioned = __is_partitioned::__fn{}; +inline constexpr auto is_partitioned = __is_partitioned::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_permutation.h b/lib/libcxx/include/__algorithm/ranges_is_permutation.h index b617500ea0..2b99839bc6 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_permutation.h +++ b/lib/libcxx/include/__algorithm/ranges_is_permutation.h @@ -25,65 +25,78 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_permutation { struct __fn { - - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __is_permutation_func_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + template + _LIBCPP_HIDE_FROM_ABI constexpr static bool __is_permutation_func_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { return std::__is_permutation<_RangeAlgPolicy>( - std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), - __pred, __proj1, __proj2); + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_equivalence_relation, - projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template < + forward_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __is_permutation_func_impl( - std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), - __pred, __proj1, __proj2); + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } template , _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, _Range2&& __range2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) return false; } return __is_permutation_func_impl( - ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), ranges::end(__range2), - __pred, __proj1, __proj2); + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2); } }; } // namespace __is_permutation inline namespace __cpo { - inline constexpr auto is_permutation = __is_permutation::__fn{}; +inline constexpr auto is_permutation = __is_permutation::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_sorted.h b/lib/libcxx/include/__algorithm/ranges_is_sorted.h index ce3032ff22..3eb2c768d6 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_sorted.h +++ b/lib/libcxx/include/__algorithm/ranges_is_sorted.h @@ -23,26 +23,27 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_sorted { struct __fn { - template _Sent, - class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; } template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __last = ranges::end(__range); return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; } @@ -50,12 +51,12 @@ struct __fn { } // namespace __is_sorted inline namespace __cpo { - inline constexpr auto is_sorted = __is_sorted::__fn{}; +inline constexpr auto is_sorted = __is_sorted::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_sorted_until.h b/lib/libcxx/include/__algorithm/ranges_is_sorted_until.h index 17fc42e97f..19e9875d27 100644 --- a/lib/libcxx/include/__algorithm/ranges_is_sorted_until.h +++ b/lib/libcxx/include/__algorithm/ranges_is_sorted_until.h @@ -24,15 +24,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI constexpr -_Iter __is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Iter +__is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { if (__first == __last) return __first; auto __i = __first; @@ -46,31 +46,32 @@ _Iter __is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& namespace __is_sorted_until { struct __fn { - template _Sent, - class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); } template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } }; } // namespace __is_sorted_until inline namespace __cpo { - inline constexpr auto is_sorted_until = __is_sorted_until::__fn{}; +inline constexpr auto is_sorted_until = __is_sorted_until::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H diff --git a/lib/libcxx/include/__algorithm/ranges_iterator_concept.h b/lib/libcxx/include/__algorithm/ranges_iterator_concept.h index 3ac6b31703..9a92030403 100644 --- a/lib/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/lib/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -46,6 +46,6 @@ using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H diff --git a/lib/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/lib/libcxx/include/__algorithm/ranges_lexicographical_compare.h index 2972e32716..5b843dfd7b 100644 --- a/lib/libcxx/include/__algorithm/ranges_lexicographical_compare.h +++ b/lib/libcxx/include/__algorithm/ranges_lexicographical_compare.h @@ -23,24 +23,24 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __lexicographical_compare { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __lexicographical_compare_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp& __comp, - _Proj1& __proj1, - _Proj2& __proj2) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __lexicographical_compare_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp& __comp, + _Proj1& __proj1, + _Proj2& __proj2) { while (__first2 != __last2) { - if (__first1 == __last1 - || std::invoke(__comp, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) + if (__first1 == __last1 || std::invoke(__comp, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) return true; if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) return false; @@ -50,49 +50,52 @@ struct __fn { return false; } - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, + template _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __lexicographical_compare_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __comp, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __comp, __proj1, __proj2); } template , _Proj1>, - projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - return __lexicographical_compare_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __comp, - __proj1, - __proj2); + indirect_strict_weak_order, _Proj1>, projected, _Proj2>> + _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __comp, + __proj1, + __proj2); } - }; } // namespace __lexicographical_compare inline namespace __cpo { - inline constexpr auto lexicographical_compare = __lexicographical_compare::__fn{}; +inline constexpr auto lexicographical_compare = __lexicographical_compare::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H diff --git a/lib/libcxx/include/__algorithm/ranges_lower_bound.h b/lib/libcxx/include/__algorithm/ranges_lower_bound.h index 78cbb6d4fb..58b3f815b9 100644 --- a/lib/libcxx/include/__algorithm/ranges_lower_bound.h +++ b/lib/libcxx/include/__algorithm/ranges_lower_bound.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,32 +35,34 @@ namespace ranges { namespace __lower_bound { struct __fn { - template _Sent, class _Type, class _Proj = identity, + template _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { - return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, - const _Type& __value, - _Comp __comp = {}, - _Proj __proj = {}) const { - return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + return std::__lower_bound<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); } }; } // namespace __lower_bound inline namespace __cpo { - inline constexpr auto lower_bound = __lower_bound::__fn{}; +inline constexpr auto lower_bound = __lower_bound::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H diff --git a/lib/libcxx/include/__algorithm/ranges_make_heap.h b/lib/libcxx/include/__algorithm/ranges_make_heap.h index f25c7ab588..f17eabff43 100644 --- a/lib/libcxx/include/__algorithm/ranges_make_heap.h +++ b/lib/libcxx/include/__algorithm/ranges_make_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __make_heap { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __make_heap_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); @@ -53,15 +53,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __make_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __make_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __make_heap inline namespace __cpo { - inline constexpr auto make_heap = __make_heap::__fn{}; +inline constexpr auto make_heap = __make_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_max.h b/lib/libcxx/include/__algorithm/ranges_max.h index 55aef99769..5cc418d339 100644 --- a/lib/libcxx/include/__algorithm/ranges_max.h +++ b/lib/libcxx/include/__algorithm/ranges_max.h @@ -20,6 +20,7 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_trivially_copyable.h> #include <__utility/move.h> #include @@ -27,44 +28,50 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __max { struct __fn { - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, + _LIBCPP_LIFETIMEBOUND const _Tp& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { return std::invoke(__comp, std::invoke(__proj, __a), std::invoke(__proj, __b)) ? __b : __a; } - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list must contain at least one element"); auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); } - template , _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); + auto __last = ranges::end(__r); - _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range must contain at least one element"); - if constexpr (forward_range<_Rp>) { + if constexpr (forward_range<_Rp> && !__is_cheap_to_copy>) { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); } else { @@ -80,7 +87,7 @@ struct __fn { } // namespace __max inline namespace __cpo { - inline constexpr auto max = __max::__fn{}; +inline constexpr auto max = __max::__fn{}; } // namespace __cpo } // namespace ranges @@ -88,6 +95,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 && +#endif // _LIBCPP_STD_VER >= 20 && #endif // _LIBCPP___ALGORITHM_RANGES_MAX_H diff --git a/lib/libcxx/include/__algorithm/ranges_max_element.h b/lib/libcxx/include/__algorithm/ranges_max_element.h index 490f32075a..2d92661c81 100644 --- a/lib/libcxx/include/__algorithm/ranges_max_element.h +++ b/lib/libcxx/include/__algorithm/ranges_max_element.h @@ -24,25 +24,28 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __max_element { struct __fn { - template _Sp, class _Proj = identity, + template _Sp, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _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) { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); } @@ -50,12 +53,12 @@ struct __fn { } // namespace __max_element inline namespace __cpo { - inline constexpr auto max_element = __max_element::__fn{}; +inline constexpr auto max_element = __max_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/ranges_merge.h b/lib/libcxx/include/__algorithm/ranges_merge.h index b36a05abc4..7f49154ec9 100644 --- a/lib/libcxx/include/__algorithm/ranges_merge.h +++ b/lib/libcxx/include/__algorithm/ranges_merge.h @@ -20,14 +20,14 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,25 +38,25 @@ using merge_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __merge { -template < - class _InIter1, - class _Sent1, - class _InIter2, - class _Sent2, - class _OutIter, - class _Comp, - class _Proj1, - class _Proj2> -_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, __remove_cvref_t<_InIter2>, __remove_cvref_t<_OutIter>> -__merge_impl( - _InIter1&& __first1, - _Sent1&& __last1, - _InIter2&& __first2, - _Sent2&& __last2, - _OutIter&& __result, - _Comp&& __comp, - _Proj1&& __proj1, - _Proj2&& __proj2) { +template < class _InIter1, + class _Sent1, + class _InIter2, + class _Sent2, + class _OutIter, + class _Comp, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, + __remove_cvref_t<_InIter2>, + __remove_cvref_t<_OutIter>> +__merge_impl(_InIter1&& __first1, + _Sent1&& __last1, + _InIter2&& __first2, + _Sent2&& __last2, + _OutIter&& __result, + _Comp&& __comp, + _Proj1&& __proj1, + _Proj2&& __proj2) { for (; __first1 != __last1 && __first2 != __last2; ++__result) { if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) { *__result = *__first2; @@ -72,15 +72,14 @@ __merge_impl( } struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr merge_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -94,28 +93,20 @@ struct __fn { return __merge::__merge_impl(__first1, __last1, __first2, __last2, __result, __comp, __proj1, __proj2); } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> + template + requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr merge_result, borrowed_iterator_t<_Range2>, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __merge::__merge_impl( ranges::begin(__range1), ranges::end(__range1), @@ -131,12 +122,12 @@ struct __fn { } // namespace __merge inline namespace __cpo { - inline constexpr auto merge = __merge::__fn{}; +inline constexpr auto merge = __merge::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H diff --git a/lib/libcxx/include/__algorithm/ranges_min.h b/lib/libcxx/include/__algorithm/ranges_min.h index 0e31f57fb8..be15b45367 100644 --- a/lib/libcxx/include/__algorithm/ranges_min.h +++ b/lib/libcxx/include/__algorithm/ranges_min.h @@ -20,48 +20,53 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_trivially_copyable.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __min { struct __fn { - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, + _LIBCPP_LIFETIMEBOUND const _Tp& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a; } - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list must contain at least one element"); return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj); } - template , _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - - _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); - - if constexpr (forward_range<_Rp>) { + auto __last = ranges::end(__r); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range must contain at least one element"); + if constexpr (forward_range<_Rp> && !__is_cheap_to_copy>) { return *ranges::__min_element_impl(__first, __last, __comp, __proj); } else { range_value_t<_Rp> __result = *__first; @@ -76,7 +81,7 @@ struct __fn { } // namespace __min inline namespace __cpo { - inline constexpr auto min = __min::__fn{}; +inline constexpr auto min = __min::__fn{}; } // namespace __cpo } // namespace ranges @@ -84,6 +89,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 && +#endif // _LIBCPP_STD_VER >= 20 && #endif // _LIBCPP___ALGORITHM_RANGES_MIN_H diff --git a/lib/libcxx/include/__algorithm/ranges_min_element.h b/lib/libcxx/include/__algorithm/ranges_min_element.h index 1751874d03..07826a0e6b 100644 --- a/lib/libcxx/include/__algorithm/ranges_min_element.h +++ b/lib/libcxx/include/__algorithm/ranges_min_element.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,8 +32,7 @@ namespace ranges { // TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`. template -_LIBCPP_HIDE_FROM_ABI static constexpr -_Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { if (__first == __last) return __first; @@ -46,29 +45,32 @@ _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { namespace __min_element { struct __fn { - template _Sp, class _Proj = identity, + template _Sp, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _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); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _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); } }; } // namespace __min_element inline namespace __cpo { - inline constexpr auto min_element = __min_element::__fn{}; +inline constexpr auto min_element = __min_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/ranges_minmax.h b/lib/libcxx/include/__algorithm/ranges_minmax.h index f82e00551e..a5b5cf9bd0 100644 --- a/lib/libcxx/include/__algorithm/ranges_minmax.h +++ b/lib/libcxx/include/__algorithm/ranges_minmax.h @@ -13,14 +13,18 @@ #include <__algorithm/minmax_element.h> #include <__assert> #include <__concepts/copyable.h> +#include <__concepts/same_as.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> +#include <__iterator/next.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -30,10 +34,10 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD @@ -43,46 +47,67 @@ using minmax_result = min_max_result<_T1>; namespace __minmax { struct __fn { - template > _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result - operator()(const _Type& __a, const _Type& __b, _Comp __comp = {}, _Proj __proj = {}) const { + operator()(_LIBCPP_LIFETIMEBOUND const _Type& __a, + _LIBCPP_LIFETIMEBOUND const _Type& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { if (std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a))) return {__b, __a}; return {__a, __b}; } - template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list has to contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> + operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list has to contain at least one element"); auto __iters = std::__minmax_element_impl(__il.begin(), __il.end(), __comp, __proj); - return ranges::minmax_result<_Type> { *__iters.first, *__iters.second }; + return ranges::minmax_result<_Type>{*__iters.first, *__iters.second}; } - template , _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Range>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_result> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); using _ValueT = range_value_t<_Range>; - _LIBCPP_ASSERT(__first != __last, "range has to contain at least one element"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range has to contain at least one element"); if constexpr (forward_range<_Range>) { + // Special-case the one element case. Avoid repeatedly initializing objects from the result of an iterator + // dereference when doing so might not be idempotent. The `if constexpr` avoids the extra branch in cases where + // it's not needed. + if constexpr (!same_as>, _ValueT> || + is_rvalue_reference_v>) { + if (ranges::next(__first) == __last) { + // During initialization, members are allowed to refer to already initialized members + // (see http://eel.is/c++draft/dcl.init.aggr#6) + minmax_result<_ValueT> __result = {*__first, __result.min}; + return __result; + } + } auto __result = std::__minmax_element_impl(__first, __last, __comp, __proj); return {*__result.first, *__result.second}; } else { // input_iterators can't be copied, so the implementation for input_iterators has to store // the values instead of a pointer to the correct values auto __less = [&](auto&& __a, auto&& __b) -> bool { - return std::invoke(__comp, std::invoke(__proj, std::forward(__a)), - std::invoke(__proj, std::forward(__b))); + return std::invoke(__comp, + std::invoke(__proj, std::forward(__a)), + std::invoke(__proj, std::forward(__b))); }; + // During initialization, members are allowed to refer to already initialized members + // (see http://eel.is/c++draft/dcl.init.aggr#6) ranges::minmax_result<_ValueT> __result = {*__first, __result.min}; if (__first == __last || ++__first == __last) return __result; @@ -121,7 +146,7 @@ struct __fn { } // namespace __minmax inline namespace __cpo { - inline constexpr auto minmax = __minmax::__fn{}; +inline constexpr auto minmax = __minmax::__fn{}; } // namespace __cpo } // namespace ranges @@ -129,6 +154,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/lib/libcxx/include/__algorithm/ranges_minmax_element.h b/lib/libcxx/include/__algorithm/ranges_minmax_element.h index 6699f9626e..a52319f6b5 100644 --- a/lib/libcxx/include/__algorithm/ranges_minmax_element.h +++ b/lib/libcxx/include/__algorithm/ranges_minmax_element.h @@ -23,13 +23,12 @@ #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,18 +39,20 @@ using minmax_element_result = min_max_result<_T1>; namespace __minmax_element { struct __fn { - template _Sp, class _Proj = identity, + template _Sp, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> + operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); return {__ret.first, __ret.second}; } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_element_result> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); return {__ret.first, __ret.second}; @@ -60,13 +61,13 @@ struct __fn { } // namespace __minmax_element inline namespace __cpo { - inline constexpr auto minmax_element = __minmax_element::__fn{}; +inline constexpr auto minmax_element = __minmax_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/lib/libcxx/include/__algorithm/ranges_mismatch.h b/lib/libcxx/include/__algorithm/ranges_mismatch.h index 4fd0517928..db9bfc8e87 100644 --- a/lib/libcxx/include/__algorithm/ranges_mismatch.h +++ b/lib/libcxx/include/__algorithm/ranges_mismatch.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -36,12 +36,9 @@ using mismatch_result = in_in_result<_I1, _I2>; namespace __mismatch { struct __fn { - template - static _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result<_I1, _I2> - __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, - _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + template + static _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> + __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { while (__first1 != __last1 && __first2 != __last2) { if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) break; @@ -51,34 +48,41 @@ struct __fn { return {std::move(__first1), std::move(__first2)}; } - template _S1, - input_iterator _I2, sentinel_for<_I2> _S2, - class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> + template _S1, + input_iterator _I2, + sentinel_for<_I2> _S2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( + _I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + const { return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); } - template + template requires indirectly_comparable, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result, borrowed_iterator_t<_R2>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result, + borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - return __go(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), - __pred, __proj1, __proj2); + return __go( + ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), __pred, __proj1, __proj2); } }; } // namespace __mismatch inline namespace __cpo { - constexpr inline auto mismatch = __mismatch::__fn{}; +constexpr inline auto mismatch = __mismatch::__fn{}; } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/ranges_move.h b/lib/libcxx/include/__algorithm/ranges_move.h index 46a0970f83..8bd2409f89 100644 --- a/lib/libcxx/include/__algorithm/ranges_move.h +++ b/lib/libcxx/include/__algorithm/ranges_move.h @@ -23,7 +23,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,38 +34,36 @@ using move_result = in_out_result<_InIter, _OutIter>; namespace __move { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static move_result<_InIter, _OutIter> + __move_impl(_InIter __first, _Sent __last, _OutIter __result) { auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template _Sent, weakly_incrementable _OutIter> requires indirectly_movable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return __move_impl(std::move(__first), std::move(__last), std::move(__result)); } template requires indirectly_movable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_result, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_result, _OutIter> + operator()(_Range&& __range, _OutIter __result) const { return __move_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); } - }; } // namespace __move inline namespace __cpo { - inline constexpr auto move = __move::__fn{}; +inline constexpr auto move = __move::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MOVE_H diff --git a/lib/libcxx/include/__algorithm/ranges_move_backward.h b/lib/libcxx/include/__algorithm/ranges_move_backward.h index d4e8eb1a50..ee390a40e4 100644 --- a/lib/libcxx/include/__algorithm/ranges_move_backward.h +++ b/lib/libcxx/include/__algorithm/ranges_move_backward.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,38 +36,36 @@ using move_backward_result = in_out_result<_InIter, _OutIter>; namespace __move_backward { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static move_backward_result<_InIter, _OutIter> + __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { auto __ret = std::__move_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template _Sent, bidirectional_iterator _OutIter> requires indirectly_movable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_backward_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_backward_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return __move_backward_impl(std::move(__first), std::move(__last), std::move(__result)); } template requires indirectly_movable, _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_backward_result, _Iter> operator()(_Range&& __range, _Iter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_backward_result, _Iter> + operator()(_Range&& __range, _Iter __result) const { return __move_backward_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); } - }; } // namespace __move_backward inline namespace __cpo { - inline constexpr auto move_backward = __move_backward::__fn{}; +inline constexpr auto move_backward = __move_backward::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H diff --git a/lib/libcxx/include/__algorithm/ranges_next_permutation.h b/lib/libcxx/include/__algorithm/ranges_next_permutation.h index 6c8e8e1529..9ebab3ea7c 100644 --- a/lib/libcxx/include/__algorithm/ranges_next_permutation.h +++ b/lib/libcxx/include/__algorithm/ranges_next_permutation.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -68,6 +68,6 @@ constexpr inline auto next_permutation = __next_permutation::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_none_of.h b/lib/libcxx/include/__algorithm/ranges_none_of.h index b39e570fd3..b0d363895e 100644 --- a/lib/libcxx/include/__algorithm/ranges_none_of.h +++ b/lib/libcxx/include/__algorithm/ranges_none_of.h @@ -22,17 +22,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __none_of { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __none_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __none_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) return false; @@ -40,29 +39,32 @@ struct __fn { return true; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __none_of inline namespace __cpo { - inline constexpr auto none_of = __none_of::__fn{}; +inline constexpr auto none_of = __none_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NONE_OF_H diff --git a/lib/libcxx/include/__algorithm/ranges_nth_element.h b/lib/libcxx/include/__algorithm/ranges_nth_element.h index d9ec4f1382..7abdbd0889 100644 --- a/lib/libcxx/include/__algorithm/ranges_nth_element.h +++ b/lib/libcxx/include/__algorithm/ranges_nth_element.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,8 @@ namespace __nth_element { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -52,16 +52,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __nth_element_fn_impl(std::move(__first), std::move(__nth), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {}, _Proj __proj = {}) const { return __nth_element_fn_impl(ranges::begin(__r), std::move(__nth), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +68,12 @@ struct __fn { } // namespace __nth_element inline namespace __cpo { - inline constexpr auto nth_element = __nth_element::__fn{}; +inline constexpr auto nth_element = __nth_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/ranges_partial_sort.h b/lib/libcxx/include/__algorithm/ranges_partial_sort.h index 3ea0a7fb44..9ec8882097 100644 --- a/lib/libcxx/include/__algorithm/ranges_partial_sort.h +++ b/lib/libcxx/include/__algorithm/ranges_partial_sort.h @@ -33,7 +33,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,24 +42,23 @@ namespace __partial_sort { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { auto&& __projected_comp = std::__make_projected(__comp, __proj); return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp); } template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __partial_sort_fn_impl(std::move(__first), std::move(__middle), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { return __partial_sort_fn_impl(ranges::begin(__r), std::move(__middle), ranges::end(__r), __comp, __proj); } }; @@ -67,12 +66,12 @@ struct __fn { } // namespace __partial_sort inline namespace __cpo { - inline constexpr auto partial_sort = __partial_sort::__fn{}; +inline constexpr auto partial_sort = __partial_sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H diff --git a/lib/libcxx/include/__algorithm/ranges_partial_sort_copy.h b/lib/libcxx/include/__algorithm/ranges_partial_sort_copy.h index 212db555a8..eba7d9ac41 100644 --- a/lib/libcxx/include/__algorithm/ranges_partial_sort_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_partial_sort_copy.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,51 +42,68 @@ using partial_sort_copy_result = in_out_result<_InIter, _OutIter>; namespace __partial_sort_copy { struct __fn { - - template _Sent1, - random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Comp = ranges::less, class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_copyable<_Iter1, _Iter2> && sortable<_Iter2, _Comp, _Proj2> && - indirect_strict_weak_order<_Comp, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> - _LIBCPP_HIDE_FROM_ABI constexpr - partial_sort_copy_result<_Iter1, _Iter2> - operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template _Sent1, + random_access_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> && sortable<_Iter2, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr partial_sort_copy_result<_Iter1, _Iter2> operator()( + _Iter1 __first, + _Sent1 __last, + _Iter2 __result_first, + _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( - std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last), - __comp, __proj1, __proj2 - ); + std::move(__first), + std::move(__last), + std::move(__result_first), + std::move(__result_last), + __comp, + __proj1, + __proj2); return {std::move(__result.first), std::move(__result.second)}; } - template - requires indirectly_copyable, iterator_t<_Range2>> && - sortable, _Comp, _Proj2> && - indirect_strict_weak_order<_Comp, projected, _Proj1>, - projected, _Proj2>> - _LIBCPP_HIDE_FROM_ABI constexpr - partial_sort_copy_result, borrowed_iterator_t<_Range2>> - operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template + requires indirectly_copyable, iterator_t<_Range2>> && + sortable, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr partial_sort_copy_result, borrowed_iterator_t<_Range2>> + operator()( + _Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range), - __comp, __proj1, __proj2 - ); + ranges::begin(__range), + ranges::end(__range), + ranges::begin(__result_range), + ranges::end(__result_range), + __comp, + __proj1, + __proj2); return {std::move(__result.first), std::move(__result.second)}; } - }; } // namespace __partial_sort_copy inline namespace __cpo { - inline constexpr auto partial_sort_copy = __partial_sort_copy::__fn{}; +inline constexpr auto partial_sort_copy = __partial_sort_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_partition.h b/lib/libcxx/include/__algorithm/ranges_partition.h index 8b3aae5c25..89d192b51f 100644 --- a/lib/libcxx/include/__algorithm/ranges_partition.h +++ b/lib/libcxx/include/__algorithm/ranges_partition.h @@ -27,13 +27,12 @@ #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,43 +40,44 @@ namespace ranges { namespace __partition { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI static constexpr - subrange<__remove_cvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + _LIBCPP_HIDE_FROM_ABI static constexpr subrange<__remove_cvref_t<_Iter>> + __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto&& __projected_pred = std::__make_projected(__pred, __proj); - auto __result = std::__partition<_RangeAlgPolicy>( + auto __result = std::__partition<_RangeAlgPolicy>( std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>()); return {std::move(__result.first), std::move(__result.second)}; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __partition_fn_impl(__first, __last, __pred, __proj); } - template , _Proj>> _Pred> - requires permutable> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __partition inline namespace __cpo { - inline constexpr auto partition = __partition::__fn{}; +inline constexpr auto partition = __partition::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_H diff --git a/lib/libcxx/include/__algorithm/ranges_partition_copy.h b/lib/libcxx/include/__algorithm/ranges_partition_copy.h index e7a9a347df..6a16b02db3 100644 --- a/lib/libcxx/include/__algorithm/ranges_partition_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_partition_copy.h @@ -19,14 +19,14 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,14 +38,18 @@ using partition_copy_result = in_out_out_result<_InIter, _OutIter1, _OutIter2>; namespace __partition_copy { struct __fn { - // TODO(ranges): delegate to the classic algorithm. template - _LIBCPP_HIDE_FROM_ABI constexpr - static partition_copy_result< - __remove_cvref_t<_InIter>, __remove_cvref_t<_OutIter1>, __remove_cvref_t<_OutIter2> - > __partition_copy_fn_impl( _InIter&& __first, _Sent&& __last, _OutIter1&& __out_true, _OutIter2&& __out_false, - _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static partition_copy_result<__remove_cvref_t<_InIter>, + __remove_cvref_t<_OutIter1>, + __remove_cvref_t<_OutIter2> > + __partition_copy_fn_impl( + _InIter&& __first, + _Sent&& __last, + _OutIter1&& __out_true, + _OutIter2&& __out_false, + _Pred& __pred, + _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) { *__out_true = *__first; @@ -60,39 +64,42 @@ struct __fn { return {std::move(__first), std::move(__out_true), std::move(__out_false)}; } - template _Sent, - weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, - class _Proj = identity, indirect_unary_predicate> _Pred> - requires indirectly_copyable<_InIter, _OutIter1> && indirectly_copyable<_InIter, _OutIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - partition_copy_result<_InIter, _OutIter1, _OutIter2> - operator()(_InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, - _Pred __pred, _Proj __proj = {}) const { + template _Sent, + weakly_incrementable _OutIter1, + weakly_incrementable _OutIter2, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter1> && indirectly_copyable<_InIter, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr partition_copy_result<_InIter, _OutIter1, _OutIter2> operator()( + _InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) + const { return __partition_copy_fn_impl( std::move(__first), std::move(__last), std::move(__out_true), std::move(__out_false), __pred, __proj); } - template , _Proj>> _Pred> - requires indirectly_copyable, _OutIter1> && indirectly_copyable, _OutIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - partition_copy_result, _OutIter1, _OutIter2> + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter1> && indirectly_copyable, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr partition_copy_result, _OutIter1, _OutIter2> operator()(_Range&& __range, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) const { return __partition_copy_fn_impl( ranges::begin(__range), ranges::end(__range), std::move(__out_true), std::move(__out_false), __pred, __proj); } - }; } // namespace __partition_copy inline namespace __cpo { - inline constexpr auto partition_copy = __partition_copy::__fn{}; +inline constexpr auto partition_copy = __partition_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_partition_point.h b/lib/libcxx/include/__algorithm/ranges_partition_point.h index 2bd118d4de..6fc20e7d00 100644 --- a/lib/libcxx/include/__algorithm/ranges_partition_point.h +++ b/lib/libcxx/include/__algorithm/ranges_partition_point.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,16 +35,15 @@ namespace ranges { namespace __partition_point { struct __fn { - // TODO(ranges): delegate to the classic algorithm. template - _LIBCPP_HIDE_FROM_ABI constexpr - static _Iter __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { auto __len = ranges::distance(__first, __last); while (__len != 0) { auto __half_len = std::__half_positive(__len); - auto __mid = ranges::next(__first, __half_len); + auto __mid = ranges::next(__first, __half_len); if (std::invoke(__pred, std::invoke(__proj, *__mid))) { __first = ++__mid; @@ -58,31 +57,32 @@ struct __fn { return __first; } - template _Sent, class _Proj = identity, + template _Sent, + class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __partition_point_fn_impl(std::move(__first), std::move(__last), __pred, __proj); } - template , _Proj>> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __partition_point_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __partition_point inline namespace __cpo { - inline constexpr auto partition_point = __partition_point::__fn{}; +inline constexpr auto partition_point = __partition_point::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H diff --git a/lib/libcxx/include/__algorithm/ranges_pop_heap.h b/lib/libcxx/include/__algorithm/ranges_pop_heap.h index 65beec8864..364cfe94b1 100644 --- a/lib/libcxx/include/__algorithm/ranges_pop_heap.h +++ b/lib/libcxx/include/__algorithm/ranges_pop_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,10 +41,10 @@ namespace __pop_heap { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __pop_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __pop_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto __len = __last_iter - __first; + auto __len = __last_iter - __first; auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len); @@ -54,15 +54,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __pop_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __pop_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -70,12 +70,12 @@ struct __fn { } // namespace __pop_heap inline namespace __cpo { - inline constexpr auto pop_heap = __pop_heap::__fn{}; +inline constexpr auto pop_heap = __pop_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_prev_permutation.h b/lib/libcxx/include/__algorithm/ranges_prev_permutation.h index 6866d90cf4..ae7a68cce5 100644 --- a/lib/libcxx/include/__algorithm/ranges_prev_permutation.h +++ b/lib/libcxx/include/__algorithm/ranges_prev_permutation.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,9 +40,7 @@ using prev_permutation_result = in_found_result<_InIter>; namespace __prev_permutation { struct __fn { - - template _Sent, - class _Comp = ranges::less, class _Proj = identity> + template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -51,8 +49,7 @@ struct __fn { return {std::move(__result.first), std::move(__result.second)}; } - template + template requires sortable, _Comp, _Proj> _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { @@ -60,7 +57,6 @@ struct __fn { ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); return {std::move(__result.first), std::move(__result.second)}; } - }; } // namespace __prev_permutation @@ -72,6 +68,6 @@ constexpr inline auto prev_permutation = __prev_permutation::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_push_heap.h b/lib/libcxx/include/__algorithm/ranges_push_heap.h index a1f4347417..1ed9c953f5 100644 --- a/lib/libcxx/include/__algorithm/ranges_push_heap.h +++ b/lib/libcxx/include/__algorithm/ranges_push_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __push_heap { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __push_heap_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); @@ -53,15 +53,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __push_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __push_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __push_heap inline namespace __cpo { - inline constexpr auto push_heap = __push_heap::__fn{}; +inline constexpr auto push_heap = __push_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_remove.h b/lib/libcxx/include/__algorithm/ranges_remove.h index dd5c5fb453..bf0928df59 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove.h +++ b/lib/libcxx/include/__algorithm/ranges_remove.h @@ -25,27 +25,26 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __remove { struct __fn { - template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) { return __value == __other; }; return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template - requires permutable> - && indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { + requires permutable> && + indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) { return __value == __other; }; return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } @@ -53,12 +52,12 @@ struct __fn { } // namespace __remove inline namespace __cpo { - inline constexpr auto remove = __remove::__fn{}; +inline constexpr auto remove = __remove::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_H diff --git a/lib/libcxx/include/__algorithm/ranges_remove_copy.h b/lib/libcxx/include/__algorithm/ranges_remove_copy.h index 2102228667..457d593957 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_remove_copy.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,40 +37,40 @@ using remove_copy_result = in_out_result<_InIter, _OutIter>; namespace __remove_copy { - struct __fn { - template _Sent, - weakly_incrementable _OutIter, - class _Type, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __val) { return __value == __val; }; - return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); - } +struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Type, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } - template - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __val) { return __value == __val; }; - return ranges::__remove_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); - } - }; + template + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } +}; } // namespace __remove_copy inline namespace __cpo { - inline constexpr auto remove_copy = __remove_copy::__fn{}; +inline constexpr auto remove_copy = __remove_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h b/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h index 4fc67454b9..c07b4813d7 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h +++ b/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h @@ -29,7 +29,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -52,39 +52,39 @@ __remove_copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& _ namespace __remove_copy_if { - struct __fn { - template _Sent, - weakly_incrementable _OutIter, - class _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); - } +struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } - template , _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - return ranges::__remove_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); - } - }; + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } +}; } // namespace __remove_copy_if inline namespace __cpo { - inline constexpr auto remove_copy_if = __remove_copy_if::__fn{}; +inline constexpr auto remove_copy_if = __remove_copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_remove_if.h b/lib/libcxx/include/__algorithm/ranges_remove_if.h index 1f17467fc4..4b7aa2d2be 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove_if.h +++ b/lib/libcxx/include/__algorithm/ranges_remove_if.h @@ -27,15 +27,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI constexpr -subrange<_Iter> __remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> +__remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { auto __new_end = ranges::__find_if_impl(__first, __last, __pred, __proj); if (__new_end == __last) return {__new_end, __new_end}; @@ -52,12 +52,12 @@ subrange<_Iter> __remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Pr namespace __remove_if { struct __fn { - - template _Sent, + template _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -65,21 +65,20 @@ struct __fn { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __remove_if inline namespace __cpo { - inline constexpr auto remove_if = __remove_if::__fn{}; +inline constexpr auto remove_if = __remove_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_replace.h b/lib/libcxx/include/__algorithm/ranges_replace.h index 8b12beacb7..714fd5c7b0 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace.h +++ b/lib/libcxx/include/__algorithm/ranges_replace.h @@ -24,51 +24,40 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __replace { struct __fn { - - template _Sent, - class _Type1, - class _Type2, - class _Proj = identity> - requires indirectly_writable<_Iter, const _Type2&> - && indirect_binary_predicate, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, - const _Type1& __old_value, - const _Type2& __new_value, - _Proj __proj = {}) const { + template _Sent, class _Type1, class _Type2, class _Proj = identity> + requires indirectly_writable<_Iter, const _Type2&> && + indirect_binary_predicate, const _Type1*> + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()( + _Iter __first, _Sent __last, const _Type1& __old_value, const _Type2& __new_value, _Proj __proj = {}) const { auto __pred = [&](const auto& __val) { return __val == __old_value; }; return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); } - template - requires indirectly_writable, const _Type2&> - && indirect_binary_predicate, _Proj>, const _Type1*> + template + requires indirectly_writable, const _Type2&> && + indirect_binary_predicate, _Proj>, const _Type1*> _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type1& __old_value, const _Type2& __new_value, _Proj __proj = {}) const { auto __pred = [&](auto&& __val) { return __val == __old_value; }; return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); } - }; } // namespace __replace inline namespace __cpo { - inline constexpr auto replace = __replace::__fn{}; +inline constexpr auto replace = __replace::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_H diff --git a/lib/libcxx/include/__algorithm/ranges_replace_copy.h b/lib/libcxx/include/__algorithm/ranges_replace_copy.h index f87a236fbd..124ff8f2c5 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_replace_copy.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,55 +37,52 @@ using replace_copy_result = in_out_result<_InIter, _OutIter>; namespace __replace_copy { - struct __fn { - template _Sent, - class _OldType, - class _NewType, - output_iterator _OutIter, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, const _OldType*> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> - operator()(_InIter __first, - _Sent __last, - _OutIter __result, - const _OldType& __old_value, - const _NewType& __new_value, - _Proj __proj = {}) const { - auto __pred = [&](const auto& __value) { return __value == __old_value; }; - return ranges::__replace_copy_if_impl( - std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); - } +struct __fn { + template _Sent, + class _OldType, + class _NewType, + output_iterator _OutIter, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> + operator()(_InIter __first, + _Sent __last, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, + _Proj __proj = {}) const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } - template _OutIter, - class _Proj = identity> - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _OldType*> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result, _OutIter> - operator()(_Range&& __range, - _OutIter __result, - const _OldType& __old_value, - const _NewType& __new_value, - _Proj __proj = {}) const { - auto __pred = [&](const auto& __value) { return __value == __old_value; }; - return ranges::__replace_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); - } - }; + template _OutIter, + class _Proj = identity> + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result, _OutIter> operator()( + _Range&& __range, _OutIter __result, const _OldType& __old_value, const _NewType& __new_value, _Proj __proj = {}) + const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } +}; } // namespace __replace_copy inline namespace __cpo { - inline constexpr auto replace_copy = __replace_copy::__fn{}; +inline constexpr auto replace_copy = __replace_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h b/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h index b8741ec7be..10ed1fda6c 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h +++ b/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -51,43 +51,43 @@ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __repl namespace __replace_copy_if { - struct __fn { - template _Sent, - class _Type, - output_iterator _OutIter, - class _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( - _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) - const { - return ranges::__replace_copy_if_impl( - std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); - } +struct __fn { + template _Sent, + class _Type, + output_iterator _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( + _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) + const { + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } - template _OutIter, - class _Proj = identity, - indirect_unary_predicate, _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { - return ranges::__replace_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); - } - }; + template _OutIter, + class _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } +}; } // namespace __replace_copy_if inline namespace __cpo { - inline constexpr auto replace_copy_if = __replace_copy_if::__fn{}; +inline constexpr auto replace_copy_if = __replace_copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_replace_if.h b/lib/libcxx/include/__algorithm/ranges_replace_if.h index 65be3c7d76..519fa32029 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace_if.h +++ b/lib/libcxx/include/__algorithm/ranges_replace_if.h @@ -23,15 +23,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template -_LIBCPP_HIDE_FROM_ABI constexpr -_Iter __replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Iter +__replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) *__first = __new_value; @@ -41,14 +41,14 @@ _Iter __replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& namespace __replace_if { struct __fn { - - template _Sent, + template _Sent, class _Type, class _Proj = identity, indirect_unary_predicate> _Pred> requires indirectly_writable<_Iter, const _Type&> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); } @@ -61,17 +61,16 @@ struct __fn { operator()(_Range&& __range, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); } - }; } // namespace __replace_if inline namespace __cpo { - inline constexpr auto replace_if = __replace_if::__fn{}; +inline constexpr auto replace_if = __replace_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H diff --git a/lib/libcxx/include/__algorithm/ranges_reverse.h b/lib/libcxx/include/__algorithm/ranges_reverse.h index e2a5d9a825..9ec865995b 100644 --- a/lib/libcxx/include/__algorithm/ranges_reverse.h +++ b/lib/libcxx/include/__algorithm/ranges_reverse.h @@ -22,18 +22,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __reverse { struct __fn { - template _Sent> requires permutable<_Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last) const { if constexpr (random_access_iterator<_Iter>) { if (__first == __last) return __first; @@ -63,21 +61,19 @@ struct __fn { template requires permutable> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } - }; } // namespace __reverse inline namespace __cpo { - inline constexpr auto reverse = __reverse::__fn{}; +inline constexpr auto reverse = __reverse::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_H diff --git a/lib/libcxx/include/__algorithm/ranges_reverse_copy.h b/lib/libcxx/include/__algorithm/ranges_reverse_copy.h index a84b1ad780..35b9edba0b 100644 --- a/lib/libcxx/include/__algorithm/ranges_reverse_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_reverse_copy.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,32 +36,30 @@ using reverse_copy_result = in_out_result<_InIter, _OutIter>; namespace __reverse_copy { struct __fn { - template _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - reverse_copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr reverse_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return (*this)(subrange(std::move(__first), std::move(__last)), std::move(__result)); } template requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - reverse_copy_result, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr reverse_copy_result, _OutIter> + operator()(_Range&& __range, _OutIter __result) const { auto __ret = ranges::copy(std::__reverse_range(__range), std::move(__result)); return {ranges::next(ranges::begin(__range), ranges::end(__range)), std::move(__ret.out)}; } - }; } // namespace __reverse_copy inline namespace __cpo { - inline constexpr auto reverse_copy = __reverse_copy::__fn{}; +inline constexpr auto reverse_copy = __reverse_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_rotate.h b/lib/libcxx/include/__algorithm/ranges_rotate.h index 91ed4027df..ebed9bbd54 100644 --- a/lib/libcxx/include/__algorithm/ranges_rotate.h +++ b/lib/libcxx/include/__algorithm/ranges_rotate.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,39 +33,34 @@ namespace ranges { namespace __rotate { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI constexpr - static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { - auto __ret = std::__rotate<_RangeAlgPolicy>( - std::move(__first), std::move(__middle), std::move(__last)); + _LIBCPP_HIDE_FROM_ABI constexpr static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { + auto __ret = std::__rotate<_RangeAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last)); return {std::move(__ret.first), std::move(__ret.second)}; } template _Sent> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { return __rotate_fn_impl(std::move(__first), std::move(__middle), std::move(__last)); } template - requires permutable> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle) const { + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle) const { return __rotate_fn_impl(ranges::begin(__range), std::move(__middle), ranges::end(__range)); } - }; } // namespace __rotate inline namespace __cpo { - inline constexpr auto rotate = __rotate::__fn{}; +inline constexpr auto rotate = __rotate::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/lib/libcxx/include/__algorithm/ranges_rotate_copy.h b/lib/libcxx/include/__algorithm/ranges_rotate_copy.h index 52f403c16a..301672707f 100644 --- a/lib/libcxx/include/__algorithm/ranges_rotate_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_rotate_copy.h @@ -23,7 +23,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,11 +34,9 @@ using rotate_copy_result = in_out_result<_InIter, _OutIter>; namespace __rotate_copy { struct __fn { - template _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - rotate_copy_result<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr rotate_copy_result<_InIter, _OutIter> operator()(_InIter __first, _InIter __middle, _Sent __last, _OutIter __result) const { auto __res1 = ranges::copy(__middle, __last, std::move(__result)); auto __res2 = ranges::copy(__first, __middle, std::move(__res1.out)); @@ -47,22 +45,20 @@ struct __fn { template requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - rotate_copy_result, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr rotate_copy_result, _OutIter> operator()(_Range&& __range, iterator_t<_Range> __middle, _OutIter __result) const { return (*this)(ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__result)); } - }; } // namespace __rotate_copy inline namespace __cpo { - inline constexpr auto rotate_copy = __rotate_copy::__fn{}; +inline constexpr auto rotate_copy = __rotate_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_sample.h b/lib/libcxx/include/__algorithm/ranges_sample.h index a37cb64fa2..d347d82205 100644 --- a/lib/libcxx/include/__algorithm/ranges_sample.h +++ b/lib/libcxx/include/__algorithm/ranges_sample.h @@ -19,15 +19,15 @@ #include <__random/uniform_random_bit_generator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,40 +35,35 @@ namespace ranges { namespace __sample { struct __fn { - template _Sent, weakly_incrementable _OutIter, class _Gen> - requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) && - indirectly_copyable<_Iter, _OutIter> && - uniform_random_bit_generator> - _LIBCPP_HIDE_FROM_ABI - _OutIter operator()(_Iter __first, _Sent __last, - _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { + requires(forward_iterator<_Iter> || random_access_iterator<_OutIter>) && indirectly_copyable<_Iter, _OutIter> && + uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI _OutIter + operator()(_Iter __first, _Sent __last, _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); return std::__sample<_RangeAlgPolicy>( std::move(__first), std::move(__last), std::move(__out_first), __n, __adapted_gen); } template - requires (forward_range<_Range> || random_access_iterator<_OutIter>) && - indirectly_copyable, _OutIter> && - uniform_random_bit_generator> - _LIBCPP_HIDE_FROM_ABI - _OutIter operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { - return (*this)(ranges::begin(__range), ranges::end(__range), - std::move(__out_first), __n, std::forward<_Gen>(__gen)); + requires(forward_range<_Range> || random_access_iterator<_OutIter>) && + indirectly_copyable, _OutIter> && uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI _OutIter + operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { + return (*this)( + ranges::begin(__range), ranges::end(__range), std::move(__out_first), __n, std::forward<_Gen>(__gen)); } - }; } // namespace __sample inline namespace __cpo { - inline constexpr auto sample = __sample::__fn{}; +inline constexpr auto sample = __sample::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H diff --git a/lib/libcxx/include/__algorithm/ranges_search.h b/lib/libcxx/include/__algorithm/ranges_search.h index 388d5afa49..ca2326e9ab 100644 --- a/lib/libcxx/include/__algorithm/ranges_search.h +++ b/lib/libcxx/include/__algorithm/ranges_search.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -69,33 +69,33 @@ struct __fn { return {__ret.first, __ret.second}; } - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __ranges_search_impl(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); } template requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __first1 = ranges::begin(__range1); if constexpr (sized_range<_Range2>) { auto __size2 = ranges::size(__range2); @@ -119,17 +119,16 @@ struct __fn { __proj1, __proj2); } - }; } // namespace __search inline namespace __cpo { - inline constexpr auto search = __search::__fn{}; +inline constexpr auto search = __search::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_H diff --git a/lib/libcxx/include/__algorithm/ranges_search_n.h b/lib/libcxx/include/__algorithm/ranges_search_n.h index 56ec8f33d4..4e53f30f71 100644 --- a/lib/libcxx/include/__algorithm/ranges_search_n.h +++ b/lib/libcxx/include/__algorithm/ranges_search_n.h @@ -31,14 +31,13 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __search_n { struct __fn { - template _LIBCPP_HIDE_FROM_ABI static constexpr subrange<_Iter1> __ranges_search_n_impl( _Iter1 __first, _Sent1 __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) { @@ -59,36 +58,31 @@ struct __fn { } } - auto __ret = std::__search_n_forward_impl<_RangeAlgPolicy>(__first, __last, - __count, - __value, - __pred, - __proj); + auto __ret = std::__search_n_forward_impl<_RangeAlgPolicy>(__first, __last, __count, __value, __pred, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } - template _Sent, + template _Sent, class _Type, class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, - iter_difference_t<_Iter> __count, - const _Type& __value, - _Pred __pred = {}, - _Proj __proj = _Proj{}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, + _Sent __last, + iter_difference_t<_Iter> __count, + const _Type& __value, + _Pred __pred = {}, + _Proj __proj = _Proj{}) const { return __ranges_search_n_impl(__first, __last, __count, __value, __pred, __proj); } template requires indirectly_comparable, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, - range_difference_t<_Range> __count, - const _Type& __value, - _Pred __pred = {}, - _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( + _Range&& __range, range_difference_t<_Range> __count, const _Type& __value, _Pred __pred = {}, _Proj __proj = {}) + const { auto __first = ranges::begin(__range); if (__count <= 0) return {__first, __first}; @@ -106,12 +100,12 @@ struct __fn { } // namespace __search_n inline namespace __cpo { - inline constexpr auto search_n = __search_n::__fn{}; +inline constexpr auto search_n = __search_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H diff --git a/lib/libcxx/include/__algorithm/ranges_set_difference.h b/lib/libcxx/include/__algorithm/ranges_set_difference.h index 607dd687a5..a9453ed336 100644 --- a/lib/libcxx/include/__algorithm/ranges_set_difference.h +++ b/lib/libcxx/include/__algorithm/ranges_set_difference.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,15 +42,14 @@ using set_difference_result = in_out_result<_InIter, _OutIter>; namespace __set_difference { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result<_InIter1, _OutIter> operator()( _InIter1 __first1, @@ -66,22 +65,20 @@ struct __fn { return {std::move(__ret.first), std::move(__ret.second)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -96,11 +93,11 @@ struct __fn { } // namespace __set_difference inline namespace __cpo { - inline constexpr auto set_difference = __set_difference::__fn{}; +inline constexpr auto set_difference = __set_difference::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H diff --git a/lib/libcxx/include/__algorithm/ranges_set_intersection.h b/lib/libcxx/include/__algorithm/ranges_set_intersection.h index aa9fd24ced..4cdcbb7505 100644 --- a/lib/libcxx/include/__algorithm/ranges_set_intersection.h +++ b/lib/libcxx/include/__algorithm/ranges_set_intersection.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,15 +40,14 @@ using set_intersection_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __set_intersection { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -69,30 +68,22 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result, - borrowed_iterator_t<_Range2>, - _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + template + requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_intersection<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -107,11 +98,11 @@ struct __fn { } // namespace __set_intersection inline namespace __cpo { - inline constexpr auto set_intersection = __set_intersection::__fn{}; +inline constexpr auto set_intersection = __set_intersection::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H diff --git a/lib/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/lib/libcxx/include/__algorithm/ranges_set_symmetric_difference.h index bc4a906550..d8710a1c47 100644 --- a/lib/libcxx/include/__algorithm/ranges_set_symmetric_difference.h +++ b/lib/libcxx/include/__algorithm/ranges_set_symmetric_difference.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,15 +40,14 @@ using set_symmetric_difference_result = in_in_out_result<_InIter1, _InIter2, _Ou namespace __set_symmetric_difference { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -69,30 +68,22 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> + template + requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result, borrowed_iterator_t<_Range2>, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -107,11 +98,11 @@ struct __fn { } // namespace __set_symmetric_difference inline namespace __cpo { - inline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{}; +inline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H diff --git a/lib/libcxx/include/__algorithm/ranges_set_union.h b/lib/libcxx/include/__algorithm/ranges_set_union.h index f8cd45ca0e..c627166fff 100644 --- a/lib/libcxx/include/__algorithm/ranges_set_union.h +++ b/lib/libcxx/include/__algorithm/ranges_set_union.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -43,15 +43,14 @@ using set_union_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __set_union { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -72,30 +71,20 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr set_union_result, - borrowed_iterator_t<_Range2>, - _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + template + requires mergeable, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result, borrowed_iterator_t<_Range2>, _OutIter> + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_union<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -110,12 +99,12 @@ struct __fn { } // namespace __set_union inline namespace __cpo { - inline constexpr auto set_union = __set_union::__fn{}; +inline constexpr auto set_union = __set_union::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_UNION_H diff --git a/lib/libcxx/include/__algorithm/ranges_shuffle.h b/lib/libcxx/include/__algorithm/ranges_shuffle.h index a2f2c0edde..fca420058d 100644 --- a/lib/libcxx/include/__algorithm/ranges_shuffle.h +++ b/lib/libcxx/include/__algorithm/ranges_shuffle.h @@ -23,15 +23,15 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,33 +39,29 @@ namespace ranges { namespace __shuffle { struct __fn { - template _Sent, class _Gen> - requires permutable<_Iter> && uniform_random_bit_generator> - _LIBCPP_HIDE_FROM_ABI - _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { + requires permutable<_Iter> && uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); return std::__shuffle<_RangeAlgPolicy>(std::move(__first), std::move(__last), __adapted_gen); } - template - requires permutable> && uniform_random_bit_generator> - _LIBCPP_HIDE_FROM_ABI - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { + template + requires permutable> && uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { return (*this)(ranges::begin(__range), ranges::end(__range), std::forward<_Gen>(__gen)); } - }; } // namespace __shuffle inline namespace __cpo { - inline constexpr auto shuffle = __shuffle::__fn{}; +inline constexpr auto shuffle = __shuffle::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/lib/libcxx/include/__algorithm/ranges_sort.h b/lib/libcxx/include/__algorithm/ranges_sort.h index 32391df5f6..2ad0e0c233 100644 --- a/lib/libcxx/include/__algorithm/ranges_sort.h +++ b/lib/libcxx/include/__algorithm/ranges_sort.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,8 @@ namespace __sort { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __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,15 +52,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -68,12 +68,12 @@ struct __fn { } // namespace __sort inline namespace __cpo { - inline constexpr auto sort = __sort::__fn{}; +inline constexpr auto sort = __sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SORT_H diff --git a/lib/libcxx/include/__algorithm/ranges_sort_heap.h b/lib/libcxx/include/__algorithm/ranges_sort_heap.h index 9feb0f609b..365c7dba61 100644 --- a/lib/libcxx/include/__algorithm/ranges_sort_heap.h +++ b/lib/libcxx/include/__algorithm/ranges_sort_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __sort_heap { struct __fn { template - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __sort_heap_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); @@ -53,15 +53,15 @@ struct __fn { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __sort_heap inline namespace __cpo { - inline constexpr auto sort_heap = __sort_heap::__fn{}; +inline constexpr auto sort_heap = __sort_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H diff --git a/lib/libcxx/include/__algorithm/ranges_stable_partition.h b/lib/libcxx/include/__algorithm/ranges_stable_partition.h index c3469f17c7..44937fa589 100644 --- a/lib/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/lib/libcxx/include/__algorithm/ranges_stable_partition.h @@ -26,15 +26,15 @@ #include <__ranges/concepts.h> #include <__ranges/dangling.h> #include <__ranges/subrange.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,47 +42,46 @@ namespace ranges { namespace __stable_partition { struct __fn { - template - _LIBCPP_HIDE_FROM_ABI static - subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl( - _Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + _LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>> + __stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_pred = std::__make_projected(__pred, __proj); - auto __result = std::__stable_partition<_RangeAlgPolicy>( + auto __result = std::__stable_partition<_RangeAlgPolicy>( std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>()); return {std::move(__result), std::move(__last_iter)}; } - template _Sent, class _Proj = identity, + template _Sent, + 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 { + requires permutable<_Iter> + _LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(__first, __last, __pred, __proj); } - template , _Proj>> _Pred> - requires permutable> - _LIBCPP_HIDE_FROM_ABI - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + requires permutable> + _LIBCPP_HIDE_FROM_ABI 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); } - }; } // namespace __stable_partition inline namespace __cpo { - inline constexpr auto stable_partition = __stable_partition::__fn{}; +inline constexpr auto stable_partition = __stable_partition::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H diff --git a/lib/libcxx/include/__algorithm/ranges_stable_sort.h b/lib/libcxx/include/__algorithm/ranges_stable_sort.h index d3c48ddb9b..a4eed38363 100644 --- a/lib/libcxx/include/__algorithm/ranges_stable_sort.h +++ b/lib/libcxx/include/__algorithm/ranges_stable_sort.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,7 @@ namespace __stable_sort { struct __fn { template - _LIBCPP_HIDE_FROM_ABI - static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI static _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,15 +51,14 @@ struct __fn { 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 _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> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI 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); } }; @@ -68,12 +66,12 @@ struct __fn { } // namespace __stable_sort inline namespace __cpo { - inline constexpr auto stable_sort = __stable_sort::__fn{}; +inline constexpr auto stable_sort = __stable_sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H diff --git a/lib/libcxx/include/__algorithm/ranges_starts_with.h b/lib/libcxx/include/__algorithm/ranges_starts_with.h new file mode 100644 index 0000000000..7da78001d8 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_starts_with.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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_RANGES_STARTS_WITH_H +#define _LIBCPP___ALGORITHM_RANGES_STARTS_WITH_H + +#include <__algorithm/in_in_result.h> +#include <__algorithm/ranges_mismatch.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __starts_with { +struct __fn { + template _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __mismatch::__fn::__go( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + __pred, + __proj1, + __proj2) + .in2 == __last2; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __mismatch::__fn::__go( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2) + .in2 == ranges::end(__range2); + } +}; +} // namespace __starts_with +inline namespace __cpo { +inline constexpr auto starts_with = __starts_with::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___ALGORITHM_RANGES_STARTS_WITH_H diff --git a/lib/libcxx/include/__algorithm/ranges_swap_ranges.h b/lib/libcxx/include/__algorithm/ranges_swap_ranges.h index 552fd55ff8..1d0ebc0d52 100644 --- a/lib/libcxx/include/__algorithm/ranges_swap_ranges.h +++ b/lib/libcxx/include/__algorithm/ranges_swap_ranges.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,8 +35,7 @@ using swap_ranges_result = in_in_result<_I1, _I2>; namespace __swap_ranges { struct __fn { - template _S1, - input_iterator _I2, sentinel_for<_I2> _S2> + template _S1, input_iterator _I2, sentinel_for<_I2> _S2> requires indirectly_swappable<_I1, _I2> _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const { @@ -47,22 +46,20 @@ struct __fn { template requires indirectly_swappable, iterator_t<_R2>> - _LIBCPP_HIDE_FROM_ABI constexpr - swap_ranges_result, borrowed_iterator_t<_R2>> + _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2) const { - return operator()(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2)); + return operator()(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2)); } }; } // namespace __swap_ranges inline namespace __cpo { - inline constexpr auto swap_ranges = __swap_ranges::__fn{}; +inline constexpr auto swap_ranges = __swap_ranges::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H diff --git a/lib/libcxx/include/__algorithm/ranges_transform.h b/lib/libcxx/include/__algorithm/ranges_transform.h index c0981a04a9..f66a07ac02 100644 --- a/lib/libcxx/include/__algorithm/ranges_transform.h +++ b/lib/libcxx/include/__algorithm/ranges_transform.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,15 +41,9 @@ using binary_transform_result = in_in_out_result<_I1, _I2, _O1>; namespace __transform { struct __fn { private: - template - _LIBCPP_HIDE_FROM_ABI static constexpr - unary_transform_result<_InIter, _OutIter> __unary(_InIter __first, _Sent __last, - _OutIter __result, - _Func& __operation, - _Proj& __projection) { + template + _LIBCPP_HIDE_FROM_ABI static constexpr unary_transform_result<_InIter, _OutIter> + __unary(_InIter __first, _Sent __last, _OutIter __result, _Func& __operation, _Proj& __projection) { while (__first != __last) { *__result = std::invoke(__operation, std::invoke(__projection, *__first)); ++__first; @@ -59,76 +53,80 @@ private: return {std::move(__first), std::move(__result)}; } - template _LIBCPP_HIDE_FROM_ABI static constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> - __binary(_InIter1 __first1, _Sent1 __last1, - _InIter2 __first2, _Sent2 __last2, + __binary(_InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, _OutIter __result, _Func& __binary_operation, _Proj1& __projection1, _Proj2& __projection2) { while (__first1 != __last1 && __first2 != __last2) { - *__result = std::invoke(__binary_operation, std::invoke(__projection1, *__first1), - std::invoke(__projection2, *__first2)); + *__result = + std::invoke(__binary_operation, std::invoke(__projection1, *__first1), std::invoke(__projection2, *__first2)); ++__first1; ++__first2; ++__result; } return {std::move(__first1), std::move(__first2), std::move(__result)}; } + public: - template _Sent, + template _Sent, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj = identity> requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter, _Proj>>> - _LIBCPP_HIDE_FROM_ABI constexpr - unary_transform_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, - _OutIter __result, - _Func __operation, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Func __operation, _Proj __proj = {}) const { return __unary(std::move(__first), std::move(__last), std::move(__result), __operation, __proj); } - template + template requires indirectly_writable<_OutIter, indirect_result_t<_Func, projected, _Proj>>> - _LIBCPP_HIDE_FROM_ABI constexpr - unary_transform_result, _OutIter> operator()(_Range&& __range, - _OutIter __result, - _Func __operation, - _Proj __projection = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Func __operation, _Proj __projection = {}) const { return __unary(ranges::begin(__range), ranges::end(__range), std::move(__result), __operation, __projection); } - template _Sent1, - input_iterator _InIter2, sentinel_for<_InIter2> _Sent2, + template _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter1, _Proj1>, - projected<_InIter2, _Proj2>>> - _LIBCPP_HIDE_FROM_ABI constexpr - binary_transform_result<_InIter1, _InIter2, _OutIter> operator()(_InIter1 __first1, _Sent1 __last1, - _InIter2 __first2, _Sent2 __last2, - _OutIter __result, - _Func __binary_operation, - _Proj1 __projection1 = {}, - _Proj2 __projection2 = {}) const { - return __binary(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - std::move(__result), - __binary_operation, - __projection1, - __projection2); + requires indirectly_writable<_OutIter, + indirect_result_t<_Func&, projected<_InIter1, _Proj1>, projected<_InIter2, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Func __binary_operation, + _Proj1 __projection1 = {}, + _Proj2 __projection2 = {}) const { + return __binary( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); } template - requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected, _Proj1>, - projected, _Proj2>>> - _LIBCPP_HIDE_FROM_ABI constexpr - binary_transform_result, borrowed_iterator_t<_Range2>, _OutIter> + requires indirectly_writable< + _OutIter, + indirect_result_t<_Func&, projected, _Proj1>, projected, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result, + borrowed_iterator_t<_Range2>, + _OutIter> operator()(_Range1&& __range1, _Range2&& __range2, _OutIter __result, _Func __binary_operation, _Proj1 __projection1 = {}, _Proj2 __projection2 = {}) const { - return __binary(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - std::move(__result), - __binary_operation, - __projection1, - __projection2); + return __binary( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); } - }; } // namespace __transform inline namespace __cpo { - inline constexpr auto transform = __transform::__fn{}; +inline constexpr auto transform = __transform::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H diff --git a/lib/libcxx/include/__algorithm/ranges_unique.h b/lib/libcxx/include/__algorithm/ranges_unique.h index be427ccf7f..b17e01fc50 100644 --- a/lib/libcxx/include/__algorithm/ranges_unique.h +++ b/lib/libcxx/include/__algorithm/ranges_unique.h @@ -32,48 +32,46 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __unique { - struct __fn { - template < - permutable _Iter, - sentinel_for<_Iter> _Sent, - class _Proj = identity, - indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__unique<_RangeAlgPolicy>( - std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); - return {std::move(__ret.first), std::move(__ret.second)}; - } +struct __fn { + template _Sent, + class _Proj = identity, + indirect_equivalence_relation> _Comp = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = + std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } - template < - forward_range _Range, - class _Proj = identity, - indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> - requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__unique<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); - return {std::move(__ret.first), std::move(__ret.second)}; - } - }; + template , _Proj>> _Comp = ranges::equal_to> + requires permutable> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; } // namespace __unique inline namespace __cpo { - inline constexpr auto unique = __unique::__fn{}; +inline constexpr auto unique = __unique::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_H diff --git a/lib/libcxx/include/__algorithm/ranges_unique_copy.h b/lib/libcxx/include/__algorithm/ranges_unique_copy.h index 3ad47b06f5..7e89f9d97a 100644 --- a/lib/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_unique_copy.h @@ -21,7 +21,6 @@ #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__iterator/projected.h> -#include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> @@ -33,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -87,9 +86,9 @@ struct __fn { class _Proj = identity, indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> requires indirectly_copyable, _OutIter> && - (forward_iterator> || - (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || - indirectly_copyable_storable, _OutIter>) + (forward_iterator> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable, _OutIter>) _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result, _OutIter> operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique_copy<_RangeAlgPolicy>( @@ -111,6 +110,6 @@ inline constexpr auto unique_copy = __unique_copy::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H diff --git a/lib/libcxx/include/__algorithm/ranges_upper_bound.h b/lib/libcxx/include/__algorithm/ranges_upper_bound.h index a134080904..a12a0e39b0 100644 --- a/lib/libcxx/include/__algorithm/ranges_upper_bound.h +++ b/lib/libcxx/include/__algorithm/ranges_upper_bound.h @@ -25,51 +25,50 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __upper_bound { struct __fn { - template _Sent, class _Type, class _Proj = identity, + template _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { return !std::invoke(__comp, __rhs, __lhs); }; - return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp_lhs_rhs_swapped, __proj); + return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp_lhs_rhs_swapped, __proj); } - template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, - const _Type& __value, - _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { return !std::invoke(__comp, __rhs, __lhs); }; - return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), - ranges::end(__r), - __value, - __comp_lhs_rhs_swapped, - __proj); + return std::__lower_bound<_RangeAlgPolicy>( + ranges::begin(__r), ranges::end(__r), __value, __comp_lhs_rhs_swapped, __proj); } }; } // namespace __upper_bound inline namespace __cpo { - inline constexpr auto upper_bound = __upper_bound::__fn{}; +inline constexpr auto upper_bound = __upper_bound::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H diff --git a/lib/libcxx/include/__algorithm/rotate.h b/lib/libcxx/include/__algorithm/rotate.h index 8934ce095b..7ed6f18628 100644 --- a/lib/libcxx/include/__algorithm/rotate.h +++ b/lib/libcxx/include/__algorithm/rotate.h @@ -15,9 +15,9 @@ #include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_trivially_move_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__algorithm/sample.h b/lib/libcxx/include/__algorithm/sample.h index f403ba6125..c7a1898e53 100644 --- a/lib/libcxx/include/__algorithm/sample.h +++ b/lib/libcxx/include/__algorithm/sample.h @@ -16,8 +16,8 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> +#include <__type_traits/common_type.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -77,7 +77,7 @@ _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g) { - _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0, "N must be a positive number."); using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>; using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>; @@ -88,22 +88,22 @@ _SampleIterator __sample(_PopulationIterator __first, __g, _PopIterCategory()); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template inline _LIBCPP_INLINE_VISIBILITY _SampleIterator sample(_PopulationIterator __first, _PopulationIterator __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator&& __g) { - static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || - __is_cpp17_random_access_iterator<_SampleIterator>::value, + static_assert(__has_forward_iterator_category<_PopulationIterator>::value || + __has_random_access_iterator_category<_SampleIterator>::value, "SampleIterator must meet the requirements of RandomAccessIterator"); return std::__sample<_ClassicAlgPolicy>( std::move(__first), std::move(__last), std::move(__output_iter), __n, __g); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/search.h b/lib/libcxx/include/__algorithm/search.h index 93771be39e..5882a04808 100644 --- a/lib/libcxx/include/__algorithm/search.h +++ b/lib/libcxx/include/__algorithm/search.h @@ -14,12 +14,13 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_callable.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -126,8 +127,8 @@ pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2, - __enable_if_t<__is_cpp17_random_access_iterator<_Iter1>::value - && __is_cpp17_random_access_iterator<_Iter2>::value>* = nullptr) { + __enable_if_t<__has_random_access_iterator_category<_Iter1>::value + && __has_random_access_iterator_category<_Iter2>::value>* = nullptr) { auto __size2 = __last2 - __first2; if (__size2 == 0) @@ -158,10 +159,10 @@ pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2, - __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value - && __is_cpp17_forward_iterator<_Iter2>::value - && !(__is_cpp17_random_access_iterator<_Iter1>::value - && __is_cpp17_random_access_iterator<_Iter2>::value)>* = nullptr) { + __enable_if_t<__has_forward_iterator_category<_Iter1>::value + && __has_forward_iterator_category<_Iter2>::value + && !(__has_random_access_iterator_category<_Iter1>::value + && __has_random_access_iterator_category<_Iter2>::value)>* = nullptr) { return std::__search_forward_impl<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __pred, @@ -187,7 +188,7 @@ _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, return std::search(__first1, __last1, __first2, __last2, __equal_to()); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { diff --git a/lib/libcxx/include/__algorithm/search_n.h b/lib/libcxx/include/__algorithm/search_n.h index 60a0735651..7e3ddf48a2 100644 --- a/lib/libcxx/include/__algorithm/search_n.h +++ b/lib/libcxx/include/__algorithm/search_n.h @@ -14,14 +14,15 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__ranges/concepts.h> +#include <__type_traits/is_callable.h> #include <__utility/convert_to_integral.h> #include <__utility/pair.h> -#include // __convert_to_integral #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -129,7 +130,7 @@ pair<_Iter, _Iter> __search_n_impl(_Iter __first, _Sent __last, const _Type& __value, _Pred& __pred, _Proj& __proj, - __enable_if_t<__is_cpp17_random_access_iterator<_Iter>::value>* = nullptr) { + __enable_if_t<__has_random_access_iterator_category<_Iter>::value>* = nullptr) { return std::__search_n_random_access_impl<_ClassicAlgPolicy>(__first, __last, __count, __value, @@ -149,8 +150,8 @@ pair<_Iter1, _Iter1> __search_n_impl(_Iter1 __first, _Sent1 __last, const _Type& __value, _Pred& __pred, _Proj& __proj, - __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value - && !__is_cpp17_random_access_iterator<_Iter1>::value>* = nullptr) { + __enable_if_t<__has_forward_iterator_category<_Iter1>::value + && !__has_random_access_iterator_category<_Iter1>::value>* = nullptr) { return std::__search_n_forward_impl<_ClassicAlgPolicy>(__first, __last, __count, __value, diff --git a/lib/libcxx/include/__algorithm/set_difference.h b/lib/libcxx/include/__algorithm/set_difference.h index cffdc8fc4f..26a300092c 100644 --- a/lib/libcxx/include/__algorithm/set_difference.h +++ b/lib/libcxx/include/__algorithm/set_difference.h @@ -17,9 +17,9 @@ #include <__functional/identity.h> #include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -66,14 +66,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - return std::__set_difference<_ClassicAlgPolicy>( - __first1, - __last1, - __first2, - __last2, - __result, - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()).second; + return std::__set_difference<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __result, __less<>()).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/set_intersection.h b/lib/libcxx/include/__algorithm/set_intersection.h index 9fa7799aee..f2603fe136 100644 --- a/lib/libcxx/include/__algorithm/set_intersection.h +++ b/lib/libcxx/include/__algorithm/set_intersection.h @@ -89,8 +89,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_i std::move(__first2), std::move(__last2), std::move(__result), - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()) + __less<>()) .__out_; } diff --git a/lib/libcxx/include/__algorithm/set_symmetric_difference.h b/lib/libcxx/include/__algorithm/set_symmetric_difference.h index bcb0958703..832c3979bf 100644 --- a/lib/libcxx/include/__algorithm/set_symmetric_difference.h +++ b/lib/libcxx/include/__algorithm/set_symmetric_difference.h @@ -96,8 +96,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetri std::move(__first2), std::move(__last2), std::move(__result), - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/set_union.h b/lib/libcxx/include/__algorithm/set_union.h index 4d154b81e0..cf48adae03 100644 --- a/lib/libcxx/include/__algorithm/set_union.h +++ b/lib/libcxx/include/__algorithm/set_union.h @@ -92,8 +92,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( std::move(__first2), std::move(__last2), std::move(__result), - __less::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/shift_left.h b/lib/libcxx/include/__algorithm/shift_left.h index 33f06d57e2..023b56dcfc 100644 --- a/lib/libcxx/include/__algorithm/shift_left.h +++ b/lib/libcxx/include/__algorithm/shift_left.h @@ -12,7 +12,6 @@ #include <__algorithm/move.h> #include <__config> #include <__iterator/iterator_traits.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template inline _LIBCPP_INLINE_VISIBILITY constexpr @@ -33,7 +32,7 @@ shift_left(_ForwardIterator __first, _ForwardIterator __last, } _ForwardIterator __m = __first; - if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { if (__n >= __last - __first) { return __first; } @@ -49,7 +48,7 @@ shift_left(_ForwardIterator __first, _ForwardIterator __last, return _VSTD::move(__m, __last, __first); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/shift_right.h b/lib/libcxx/include/__algorithm/shift_right.h index 14bc761598..70aff45fe5 100644 --- a/lib/libcxx/include/__algorithm/shift_right.h +++ b/lib/libcxx/include/__algorithm/shift_right.h @@ -15,7 +15,6 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template inline _LIBCPP_INLINE_VISIBILITY constexpr @@ -35,14 +34,14 @@ shift_right(_ForwardIterator __first, _ForwardIterator __last, return __first; } - if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { decltype(__n) __d = __last - __first; if (__n >= __d) { return __last; } _ForwardIterator __m = __first + (__d - __n); return _VSTD::move_backward(__first, __m, __last); - } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { + } else if constexpr (__has_bidirectional_iterator_category<_ForwardIterator>::value) { _ForwardIterator __m = __last; for (; __n > 0; --__n) { if (__m == __first) { @@ -95,7 +94,7 @@ shift_right(_ForwardIterator __first, _ForwardIterator __last, } } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/shuffle.h b/lib/libcxx/include/__algorithm/shuffle.h index f7bce68697..6fee88ca6f 100644 --- a/lib/libcxx/include/__algorithm/shuffle.h +++ b/lib/libcxx/include/__algorithm/shuffle.h @@ -11,7 +11,6 @@ #include <__algorithm/iterator_operations.h> #include <__config> -#include <__debug> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> #include <__utility/forward.h> @@ -29,9 +28,9 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { +class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer { public: - __libcpp_debug_randomizer() { + _LIBCPP_HIDE_FROM_ABI __libcpp_debug_randomizer() { __state_ = __seed(); __inc_ = __state_ + 0xda3e39cb94b95bdbULL; __inc_ = (__inc_ << 1) | 1; @@ -65,11 +64,11 @@ private: #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ || defined(_LIBCPP_BUILDING_LIBRARY) -class _LIBCPP_TYPE_VIS __rs_default; +class _LIBCPP_EXPORTED_FROM_ABI __rs_default; -_LIBCPP_FUNC_VIS __rs_default __rs_get(); +_LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); -class _LIBCPP_TYPE_VIS __rs_default +class _LIBCPP_EXPORTED_FROM_ABI __rs_default { static unsigned __c_; @@ -85,13 +84,13 @@ public: result_type operator()(); - static _LIBCPP_CONSTEXPR result_type min() {return _Min;} - static _LIBCPP_CONSTEXPR result_type max() {return _Max;} + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() {return _Min;} + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() {return _Max;} - friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); + friend _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); }; -_LIBCPP_FUNC_VIS __rs_default __rs_get(); +_LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void diff --git a/lib/libcxx/include/__algorithm/sift_down.h b/lib/libcxx/include/__algorithm/sift_down.h index e3972fb6f4..20f0b0275d 100644 --- a/lib/libcxx/include/__algorithm/sift_down.h +++ b/lib/libcxx/include/__algorithm/sift_down.h @@ -19,6 +19,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -83,7 +86,7 @@ __floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; - _LIBCPP_ASSERT(__len >= 2, "shouldn't be called unless __len >= 2"); + _LIBCPP_ASSERT_UNCATEGORIZED(__len >= 2, "shouldn't be called unless __len >= 2"); _RandomAccessIterator __hole = __first; _RandomAccessIterator __child_i = __first; @@ -111,4 +114,6 @@ __floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H diff --git a/lib/libcxx/include/__algorithm/sort.h b/lib/libcxx/include/__algorithm/sort.h index a236be0a4d..3b594fa4d2 100644 --- a/lib/libcxx/include/__algorithm/sort.h +++ b/lib/libcxx/include/__algorithm/sort.h @@ -11,23 +11,27 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iter_swap.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min_element.h> #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> +#include <__assert> +#include <__bit/blsr.h> +#include <__bit/countl.h> +#include <__bit/countr.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__functional/operations.h> #include <__functional/ranges_operations.h> #include <__iterator/iterator_traits.h> -#include <__memory/destruct_n.h> -#include <__memory/unique_ptr.h> +#include <__type_traits/conditional.h> +#include <__type_traits/disjunction.h> #include <__type_traits/is_arithmetic.h> -#include <__type_traits/is_trivially_copy_assignable.h> -#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_constant_evaluated.h> #include <__utility/move.h> -#include +#include <__utility/pair.h> #include #include @@ -37,52 +41,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without -// changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag. -// -// To create an object of this type, use `_WrapAlgPolicy::type` -- see the specialization below for the rationale. -template -struct _WrapAlgPolicy { - using type = _WrapAlgPolicy; - - using _AlgPolicy = _PolicyT; - using _Comp = _CompT; - _Comp& __comp; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - _WrapAlgPolicy(_Comp& __c) : __comp(__c) {} -}; - -// Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the -// comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing -// the pristine comparator where possible allows using template instantiations from the dylib. -template -struct _WrapAlgPolicy<_PolicyT, _CompT, __enable_if_t::value> > { - using type = _CompT; -}; - -// Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always -// set to "classic". -template -struct _UnwrapAlgPolicy { - using _AlgPolicy = _ClassicAlgPolicy; - using _Comp = _CompT; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static - _Comp __get_comp(_Comp __comp) { return __comp; } -}; - -// Unwraps a `_WrapAlgPolicy` struct. -template -struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > { - using _Wrapped = _WrapAlgPolicy<_Ts...>; - using _AlgPolicy = typename _Wrapped::_AlgPolicy; - using _Comp = typename _Wrapped::_Comp; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static - _Comp __get_comp(_Wrapped& __w) { return __w.__comp; } -}; - // stable, 2-3 compares, 0-2 swaps template @@ -126,78 +84,53 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 unsigned __sort3(_ForwardIterator __x, _ForwardIte template _LIBCPP_HIDE_FROM_ABI -unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, +void __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _Compare __c) { - using _Ops = _IterOps<_AlgPolicy>; - - unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); + using _Ops = _IterOps<_AlgPolicy>; + std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); if (__c(*__x4, *__x3)) { _Ops::iter_swap(__x3, __x4); - ++__r; if (__c(*__x3, *__x2)) { _Ops::iter_swap(__x2, __x3); - ++__r; if (__c(*__x2, *__x1)) { _Ops::iter_swap(__x1, __x2); - ++__r; } } } - return __r; } // stable, 4-10 compares, 0-9 swaps -template -_LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, - _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) { - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; +template +_LIBCPP_HIDE_FROM_ABI void __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, + _ForwardIterator __x4, _ForwardIterator __x5, _Comp __comp) { using _Ops = _IterOps<_AlgPolicy>; - using _Compare = typename _Unwrap::_Comp; - _Compare __c = _Unwrap::__get_comp(__wrapped_comp); - - unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); - if (__c(*__x5, *__x4)) { + std::__sort4<_AlgPolicy, _Comp>(__x1, __x2, __x3, __x4, __comp); + if (__comp(*__x5, *__x4)) { _Ops::iter_swap(__x4, __x5); - ++__r; - if (__c(*__x4, *__x3)) { + if (__comp(*__x4, *__x3)) { _Ops::iter_swap(__x3, __x4); - ++__r; - if (__c(*__x3, *__x2)) { + if (__comp(*__x3, *__x2)) { _Ops::iter_swap(__x2, __x3); - ++__r; - if (__c(*__x2, *__x1)) { + if (__comp(*__x2, *__x1)) { _Ops::iter_swap(__x1, __x2); - ++__r; } } } } - return __r; -} - -template -_LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy( - _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5, - _Compare __c) { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; - _WrappedComp __wrapped_comp(__c); - return std::__sort5<_WrappedComp>( - std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp); } // The comparator being simple is a prerequisite for using the branchless optimization. template struct __is_simple_comparator : false_type {}; -template -struct __is_simple_comparator<__less<_Tp>&> : true_type {}; +template <> +struct __is_simple_comparator<__less<>&> : true_type {}; template struct __is_simple_comparator&> : true_type {}; template struct __is_simple_comparator&> : true_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> struct __is_simple_comparator : true_type {}; template <> @@ -206,9 +139,16 @@ struct __is_simple_comparator : true_type {}; template ::value_type> using __use_branchless_sort = - integral_constant::value && sizeof(_Tp) <= sizeof(void*) && + integral_constant::value && sizeof(_Tp) <= sizeof(void*) && is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>; +namespace __detail { + +// Size in bits for the bitset in use. +enum { __block_size = sizeof(uint64_t) * 8 }; + +} // namespace __detail + // Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary. template inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) { @@ -268,10 +208,15 @@ __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); } -template +template inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> -__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, - _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { +__sort5_maybe_branchless( + _RandomAccessIterator __x1, + _RandomAccessIterator __x2, + _RandomAccessIterator __x3, + _RandomAccessIterator __x4, + _RandomAccessIterator __x5, + _Compare __c) { std::__cond_swap<_Compare>(__x1, __x2, __c); std::__cond_swap<_Compare>(__x4, __x5, __c); std::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c); @@ -284,7 +229,8 @@ template inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { - std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c); + std::__sort5<_AlgPolicy, _Compare, _RandomAccessIterator>( + std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __c); } // Assumes size > 0 @@ -300,34 +246,49 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 void __selection_sort(_BidirectionalIterator __fir } } +// Sort the iterator range [__first, __last) using the comparator __comp using +// the insertion sort algorithm. template _LIBCPP_HIDE_FROM_ABI void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - if (__first != __last) { - _BidirectionalIterator __i = __first; - for (++__i; __i != __last; ++__i) { - _BidirectionalIterator __j = __i; - value_type __t(_Ops::__iter_move(__j)); - for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j) + if (__first == __last) + return; + _BidirectionalIterator __i = __first; + for (++__i; __i != __last; ++__i) { + _BidirectionalIterator __j = __i; + --__j; + if (__comp(*__i, *__j)) { + value_type __t(_Ops::__iter_move(__i)); + _BidirectionalIterator __k = __j; + __j = __i; + do { *__j = _Ops::__iter_move(__k); + __j = __k; + } while (__j != __first && __comp(__t, *--__k)); *__j = std::move(__t); } } } +// Sort the iterator range [__first, __last) using the comparator __comp using +// the insertion sort algorithm. Insertion sort has two loops, outer and inner. +// The implementation below has no bounds check (unguarded) for the inner loop. +// Assumes that there is an element in the position (__first - 1) and that each +// element in the input range is greater or equal to the element at __first - 1. template -_LIBCPP_HIDE_FROM_ABI -void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { +_LIBCPP_HIDE_FROM_ABI void +__insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) { using _Ops = _IterOps<_AlgPolicy>; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; - _RandomAccessIterator __j = __first + difference_type(2); - std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); - for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { + if (__first == __last) + return; + const _RandomAccessIterator __leftmost = __first - difference_type(1); (void)__leftmost; // can be unused when assertions are disabled + for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) { + _RandomAccessIterator __j = __i - difference_type(1); if (__comp(*__i, *__j)) { value_type __t(_Ops::__iter_move(__i)); _RandomAccessIterator __k = __j; @@ -335,23 +296,20 @@ void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __l do { *__j = _Ops::__iter_move(__k); __j = __k; - } while (__j != __first && __comp(__t, *--__k)); + _LIBCPP_ASSERT_UNCATEGORIZED( + __k != __leftmost, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above. *__j = std::move(__t); } - __j = __i; } } -template -_LIBCPP_HIDDEN bool __insertion_sort_incomplete( - _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; +template +_LIBCPP_HIDE_FROM_ABI bool __insertion_sort_incomplete( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { using _Ops = _IterOps<_AlgPolicy>; - using _Compare = typename _Unwrap::_Comp; - _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); - typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; switch (__last - __first) { case 0: @@ -359,24 +317,24 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete( return true; case 2: if (__comp(*--__last, *__first)) - _IterOps<_AlgPolicy>::iter_swap(__first, __last); + _Ops::iter_swap(__first, __last); return true; case 3: - std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), --__last, __comp); return true; case 4: - std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + std::__sort4_maybe_branchless<_AlgPolicy, _Comp>( __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); return true; case 5: - std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + std::__sort5_maybe_branchless<_AlgPolicy, _Comp>( __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), --__last, __comp); return true; } typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first + difference_type(2); - std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), __j, __comp); const unsigned __limit = 8; unsigned __count = 0; for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { @@ -397,48 +355,380 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete( return true; } -template -_LIBCPP_HIDE_FROM_ABI -void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, - typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { +template +inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( + _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) { using _Ops = _IterOps<_AlgPolicy>; - - typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - if (__first1 != __last1) { - __destruct_n __d(0); - unique_ptr __h(__first2, __d); - value_type* __last2 = __first2; - ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); - __d.template __incr(); - for (++__last2; ++__first1 != __last1; ++__last2) { - value_type* __j2 = __last2; - value_type* __i2 = __j2; - if (__comp(*__first1, *--__i2)) { - ::new ((void*)__j2) value_type(std::move(*__i2)); - __d.template __incr(); - for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) - *__j2 = std::move(*__i2); - *__j2 = _Ops::__iter_move(__first1); - } else { - ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); - __d.template __incr(); - } - } - __h.release(); + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + // 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); + _Ops::iter_swap(__first + __tz_left, __last - __tz_right); } } -template -void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, - typename iterator_traits<_RandomAccessIterator>::difference_type __depth) { - using _Ops = _IterOps<_AlgPolicy>; +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void +__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) { + // Possible vectorization. With a proper "-march" flag, the following loop + // will be compiled into a set of SIMD instructions. + _RandomAccessIterator __iter = __first; + for (int __j = 0; __j < __detail::__block_size;) { + bool __comp_result = !__comp(*__iter, __pivot); + __left_bitset |= (static_cast(__comp_result) << __j); + __j++; + ++__iter; + } +} +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void +__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) { + // Possible vectorization. With a proper "-march" flag, the following loop + // will be compiled into a set of SIMD instructions. + _RandomAccessIterator __iter = __lm1; + for (int __j = 0; __j < __detail::__block_size;) { + bool __comp_result = __comp(*__iter, __pivot); + __right_bitset |= (static_cast(__comp_result) << __j); + __j++; + --__iter; + } +} + +template ::value_type> +inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( + _RandomAccessIterator& __first, + _RandomAccessIterator& __lm1, + _Compare __comp, + _ValueType& __pivot, + uint64_t& __left_bitset, + uint64_t& __right_bitset) { + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __remaining_len = __lm1 - __first + 1; + difference_type __l_size; + difference_type __r_size; + if (__left_bitset == 0 && __right_bitset == 0) { + __l_size = __remaining_len / 2; + __r_size = __remaining_len - __l_size; + } else if (__left_bitset == 0) { + // We know at least one side is a full block. + __l_size = __remaining_len - __detail::__block_size; + __r_size = __detail::__block_size; + } else { // if (__right_bitset == 0) + __l_size = __detail::__block_size; + __r_size = __remaining_len - __detail::__block_size; + } + // Record the comparison outcomes for the elements currently on the left side. + if (__left_bitset == 0) { + _RandomAccessIterator __iter = __first; + for (int __j = 0; __j < __l_size; __j++) { + bool __comp_result = !__comp(*__iter, __pivot); + __left_bitset |= (static_cast(__comp_result) << __j); + ++__iter; + } + } + // Record the comparison outcomes for the elements currently on the right + // side. + if (__right_bitset == 0) { + _RandomAccessIterator __iter = __lm1; + for (int __j = 0; __j < __r_size; __j++) { + bool __comp_result = __comp(*__iter, __pivot); + __right_bitset |= (static_cast(__comp_result) << __j); + --__iter; + } + } + std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset); + __first += (__left_bitset == 0) ? __l_size : 0; + __lm1 -= (__right_bitset == 0) ? __r_size : 0; +} + +template +inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( + _RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + if (__left_bitset) { + // 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); + __left_bitset &= (static_cast(1) << __tz_left) - 1; + _RandomAccessIterator __it = __first + __tz_left; + if (__it != __lm1) { + _Ops::iter_swap(__it, __lm1); + } + --__lm1; + } + __first = __lm1 + difference_type(1); + } else if (__right_bitset) { + // 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); + __right_bitset &= (static_cast(1) << __tz_right) - 1; + _RandomAccessIterator __it = __lm1 - __tz_right; + if (__it != __first) { + _Ops::iter_swap(__it, __first); + } + ++__first; + } + } +} + +// Partition [__first, __last) using the comparator __comp. *__first has the +// chosen pivot. Elements that are equivalent are kept to the left of the +// pivot. Returns the iterator for the pivot and a bool value which is true if +// the provided range is already sorted, false otherwise. We assume that the +// length of the range is at least three elements. +// +// __bitset_partition uses bitsets for storing outcomes of the comparisons +// between the pivot and other elements. +template +_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> +__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; + _LIBCPP_ASSERT_UNCATEGORIZED(__last - __first >= difference_type(3), ""); + const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // + + value_type __pivot(_Ops::__iter_move(__first)); + // Find the first element greater than the pivot. + if (__comp(__pivot, *(__last - difference_type(1)))) { + // Not guarded since we know the last element is greater than the pivot. + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); + } else { + while (++__first < __last && !__comp(__pivot, *__first)) { + } + } + // Find the last element less than or equal to the pivot. + if (__first < __last) { + // It will be always guarded because __introsort will do the median-of-three + // before calling this. + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); + } + // If the first element greater than the pivot is at or after the + // last element less than or equal to the pivot, then we have covered the + // entire range without swapping elements. This implies the range is already + // partitioned. + bool __already_partitioned = __first >= __last; + if (!__already_partitioned) { + _Ops::iter_swap(__first, __last); + ++__first; + } + + // In [__first, __last) __last is not inclusive. From now on, it uses last + // minus one to be inclusive on both sides. + _RandomAccessIterator __lm1 = __last - difference_type(1); + uint64_t __left_bitset = 0; + uint64_t __right_bitset = 0; + + // Reminder: length = __lm1 - __first + 1. + while (__lm1 - __first >= 2 * __detail::__block_size - 1) { + // Record the comparison outcomes for the elements currently on the left + // side. + if (__left_bitset == 0) + std::__populate_left_bitset<_Compare>(__first, __comp, __pivot, __left_bitset); + // Record the comparison outcomes for the elements currently on the right + // side. + if (__right_bitset == 0) + std::__populate_right_bitset<_Compare>(__lm1, __comp, __pivot, __right_bitset); + // Swap the elements recorded to be the candidates for swapping in the + // bitsets. + std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset); + // Only advance the iterator if all the elements that need to be moved to + // other side were moved. + __first += (__left_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0); + __lm1 -= (__right_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0); + } + // Now, we have a less-than a block worth of elements on at least one of the + // sides. + std::__bitset_partition_partial_blocks<_AlgPolicy, _Compare>( + __first, __lm1, __comp, __pivot, __left_bitset, __right_bitset); + // At least one the bitsets would be empty. For the non-empty one, we need to + // properly partition the elements that appear within that bitset. + std::__swap_bitmap_pos_within<_AlgPolicy>(__first, __lm1, __left_bitset, __right_bitset); + + // Move the pivot to its correct position. + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return std::make_pair(__pivot_pos, __already_partitioned); +} + +// Partition [__first, __last) using the comparator __comp. *__first has the +// chosen pivot. Elements that are equivalent are kept to the right of the +// pivot. Returns the iterator for the pivot and a bool value which is true if +// the provided range is already sorted, false otherwise. We assume that the +// length of the range is at least three elements. +template +_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> +__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; - typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; - const difference_type __limit = - is_trivially_copy_constructible::value && is_trivially_copy_assignable::value ? 30 : 6; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + _LIBCPP_ASSERT_UNCATEGORIZED(__last - __first >= difference_type(3), ""); + const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // + value_type __pivot(_Ops::__iter_move(__first)); + // Find the first element greater or equal to the pivot. It will be always + // guarded because __introsort will do the median-of-three before calling + // this. + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (__comp(*__first, __pivot)); + + // Find the last element less than the pivot. + if (__begin == __first - difference_type(1)) { + while (__first < __last && !__comp(*--__last, __pivot)) + ; + } else { + // Guarded. + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (!__comp(*__last, __pivot)); + } + + // If the first element greater than or equal to the pivot is at or after the + // last element less than the pivot, then we have covered the entire range + // without swapping elements. This implies the range is already partitioned. + bool __already_partitioned = __first >= __last; + // Go through the remaining elements. Swap pairs of elements (one to the + // right of the pivot and the other to left of the pivot) that are not on the + // correct side of the pivot. + while (__first < __last) { + _Ops::iter_swap(__first, __last); + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (__comp(*__first, __pivot)); + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (!__comp(*__last, __pivot)); + } + // Move the pivot to its correct position. + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return std::make_pair(__pivot_pos, __already_partitioned); +} + +// Similar to the above function. Elements equivalent to the pivot are put to +// the left of the pivot. Returns the iterator to the pivot element. +template +_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator +__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; + // TODO(LLVM18): Make __begin const, see https://reviews.llvm.org/D147089#4349748 + _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // + value_type __pivot(_Ops::__iter_move(__first)); + if (__comp(__pivot, *(__last - difference_type(1)))) { + // Guarded. + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); + } else { + while (++__first < __last && !__comp(__pivot, *__first)) { + } + } + + if (__first < __last) { + // It will be always guarded because __introsort will do the + // median-of-three before calling this. + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); + } + while (__first < __last) { + _Ops::iter_swap(__first, __last); + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); + } + _RandomAccessIterator __pivot_pos = __first - difference_type(1); + if (__begin != __pivot_pos) { + *__begin = _Ops::__iter_move(__pivot_pos); + } + *__pivot_pos = std::move(__pivot); + return __first; +} + +// The main sorting function. Implements introsort combined with other ideas: +// - option of using block quick sort for partitioning, +// - guarded and unguarded insertion sort for small lengths, +// - Tuckey's ninther technique for computing the pivot, +// - check on whether partition was not required. +// The implementation is partly based on Orson Peters' pattern-defeating +// quicksort, published at: . +template +void __introsort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __depth, + bool __leftmost = true) { + using _Ops = _IterOps<_AlgPolicy>; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + using _Comp_ref = __comp_ref_type<_Compare>; + // Upper bound for using insertion sort for sorting. + _LIBCPP_CONSTEXPR difference_type __limit = 24; + // Lower bound for using Tuckey's ninther technique for median computation. + _LIBCPP_CONSTEXPR difference_type __ninther_threshold = 128; while (true) { - __restart: difference_type __len = __last - __first; switch (__len) { case 0: @@ -446,7 +736,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C return; case 2: if (__comp(*--__last, *__first)) - _IterOps<_AlgPolicy>::iter_swap(__first, __last); + _Ops::iter_swap(__first, __last); return; case 3: std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); @@ -461,131 +751,62 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C --__last, __comp); return; } - if (__len <= __limit) { - std::__insertion_sort_3<_AlgPolicy, _Compare>(__first, __last, __comp); + // Use insertion sort if the length of the range is below the specified limit. + if (__len < __limit) { + if (__leftmost) { + std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp); + } else { + std::__insertion_sort_unguarded<_AlgPolicy, _Compare>(__first, __last, __comp); + } return; } - // __len > 5 if (__depth == 0) { // Fallback to heap sort as Introsort suggests. std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp); return; } --__depth; - _RandomAccessIterator __m = __first; - _RandomAccessIterator __lm1 = __last; - --__lm1; - unsigned __n_swaps; { - difference_type __delta; - if (__len >= 1000) { - __delta = __len / 2; - __m += __delta; - __delta /= 2; - __n_swaps = std::__sort5_wrap_policy<_AlgPolicy, _Compare>( - __first, __first + __delta, __m, __m + __delta, __lm1, __comp); + difference_type __half_len = __len / 2; + // Use Tuckey's ninther technique or median of 3 for pivot selection + // depending on the length of the range being sorted. + if (__len > __ninther_threshold) { + std::__sort3<_AlgPolicy, _Compare>(__first, __first + __half_len, __last - difference_type(1), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + difference_type(1), __first + (__half_len - 1), __last - difference_type(2), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + difference_type(2), __first + (__half_len + 1), __last - difference_type(3), __comp); + std::__sort3<_AlgPolicy, _Compare>( + __first + (__half_len - 1), __first + __half_len, __first + (__half_len + 1), __comp); + _Ops::iter_swap(__first, __first + __half_len); } else { - __delta = __len / 2; - __m += __delta; - __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, __lm1, __comp); + std::__sort3<_AlgPolicy, _Compare>(__first + __half_len, __first, __last - difference_type(1), __comp); } } - // *__m is median - // partition [__first, __m) < *__m and *__m <= [__m, __last) - // (this inhibits tossing elements equivalent to __m around unnecessarily) - _RandomAccessIterator __i = __first; - _RandomAccessIterator __j = __lm1; - // j points beyond range to be tested, *__m is known to be <= *__lm1 - // The search going up is known to be guarded but the search coming down isn't. - // Prime the downward search with a guard. - if (!__comp(*__i, *__m)) // if *__first == *__m - { - // *__first == *__m, *__first doesn't go in first part - // manually guard downward moving __j against __i - while (true) { - if (__i == --__j) { - // *__first == *__m, *__m <= all other elements - // Parition instead into [__first, __i) == *__first and *__first < [__i, __last) - ++__i; // __first + 1 - __j = __last; - if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1) - { - while (true) { - if (__i == __j) - return; // [__first, __last) all equivalent elements - if (__comp(*__first, *__i)) { - _Ops::iter_swap(__i, __j); - ++__n_swaps; - ++__i; - break; - } - ++__i; - } - } - // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 - if (__i == __j) - return; - while (true) { - while (!__comp(*__first, *__i)) - ++__i; - while (__comp(*__first, *--__j)) - ; - if (__i >= __j) - break; - _Ops::iter_swap(__i, __j); - ++__n_swaps; - ++__i; - } - // [__first, __i) == *__first and *__first < [__i, __last) - // The first part is sorted, sort the second part - // std::__sort<_Compare>(__i, __last, __comp); - __first = __i; - goto __restart; - } - if (__comp(*__j, *__m)) { - _Ops::iter_swap(__i, __j); - ++__n_swaps; - break; // found guard for downward moving __j, now use unguarded partition - } - } - } - // It is known that *__i < *__m - ++__i; - // j points beyond range to be tested, *__m is known to be <= *__lm1 - // if not yet partitioned... - if (__i < __j) { - // known that *(__i - 1) < *__m - // known that __i <= __m - while (true) { - // __m still guards upward moving __i - while (__comp(*__i, *__m)) - ++__i; - // It is now known that a guard exists for downward moving __j - while (!__comp(*--__j, *__m)) - ; - if (__i > __j) - break; - _Ops::iter_swap(__i, __j); - ++__n_swaps; - // It is known that __m != __j - // If __m just moved, follow it - if (__m == __i) - __m = __j; - ++__i; - } - } - // [__first, __i) < *__m and *__m <= [__i, __last) - if (__i != __m && __comp(*__m, *__i)) { - _Ops::iter_swap(__i, __m); - ++__n_swaps; + // The elements to the left of the current iterator range are already + // sorted. If the current iterator range to be sorted is not the + // leftmost part of the entire iterator range and the pivot is same as + // the highest element in the range to the left, then we know that all + // the elements in the range [first, pivot] would be equal to the pivot, + // assuming the equal elements are put on the left side when + // partitioned. This also means that we do not need to sort the left + // side of the partition. + if (!__leftmost && !__comp(*(__first - difference_type(1)), *__first)) { + __first = std::__partition_with_equals_on_left<_AlgPolicy, _RandomAccessIterator, _Comp_ref>( + __first, __last, _Comp_ref(__comp)); + continue; } + // Use bitset partition only if asked for. + auto __ret = + _UseBitSetPartition + ? std::__bitset_partition<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp) + : std::__partition_with_equals_on_right<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp); + _RandomAccessIterator __i = __ret.first; // [__first, __i) < *__i and *__i <= [__i+1, __last) // If we were given a perfect partition, see if insertion sort is quick... - if (__n_swaps == 0) { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; - _WrappedComp __wrapped_comp(__comp); - bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp); - if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type(1), __last, __wrapped_comp)) { + if (__ret.second) { + bool __fs = std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__first, __i, __comp); + if (std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp)) { if (__fs) return; __last = __i; @@ -597,14 +818,11 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C } } } - // sort smaller range with recursive call and larger with tail recursion elimination - if (__i - __first < __last - __i) { - std::__introsort<_AlgPolicy, _Compare>(__first, __i, __comp, __depth); - __first = ++__i; - } else { - std::__introsort<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp, __depth); - __last = __i; - } + // Sort the left partiton recursively and the right partition with tail recursion elimination. + std::__introsort<_AlgPolicy, _Compare, _RandomAccessIterator, _UseBitSetPartition>( + __first, __i, __comp, __depth, __leftmost); + __leftmost = false; + __first = ++__i; } } @@ -627,77 +845,107 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { return __log2; } -template -_LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { +template +void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp); + +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, char*>(char*, char*, __less&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&); +#endif +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, signed char*>(signed char*, signed char*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, short*>(short*, short*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, unsigned short*>(unsigned short*, unsigned short*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, int*>(int*, int*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, unsigned*>(unsigned*, unsigned*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, long*>(long*, long*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, unsigned long*>(unsigned long*, unsigned long*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, long long*>(long long*, long long*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, unsigned long long*>(unsigned long long*, unsigned long long*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, float*>(float*, float*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, double*>(double*, double*, __less&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less&, long double*>(long double*, long double*, __less&); + +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); - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; - using _Compare = typename _Unwrap::_Comp; - _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); - std::__introsort<_AlgPolicy, _Compare>(__first, __last, __comp, __depth_limit); + // 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 + // branches in the comparator. + std::__introsort<_AlgPolicy, + _Comp&, + _RandomAccessIterator, + __use_branchless_sort<_Comp, _RandomAccessIterator>::value>( + __first, __last, __comp, __depth_limit); } -template -inline _LIBCPP_INLINE_VISIBILITY void __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) { - __less __comp; - std::__sort<__less&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); +template +using __is_any_of = _Or...>; + +template +using __sort_is_specialized_in_library = __is_any_of< + _Type, + char, +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + wchar_t, +#endif + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double, + long double>; + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); } -extern template _LIBCPP_FUNC_VIS void __sort<__less&, char*>(char*, char*, __less&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -extern template _LIBCPP_FUNC_VIS void __sort<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&); -#endif -extern template _LIBCPP_FUNC_VIS void __sort<__less&, signed char*>(signed char*, signed char*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, short*>(short*, short*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned short*>(unsigned short*, unsigned short*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, int*>(int*, int*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned*>(unsigned*, unsigned*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, long*>(long*, long*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned long*>(unsigned long*, unsigned long*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, long long*>(long long*, long long*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, unsigned long long*>(unsigned long long*, unsigned long long*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, float*>(float*, float*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, double*>(double*, double*, __less&); -extern template _LIBCPP_FUNC_VIS void __sort<__less&, long double*>(long double*, long double*, __less&); +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, char*>(char*, char*, __less&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&); +#if _LIBCPP_STD_VER >= 14 +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} #endif -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, signed char*>(signed char*, signed char*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, short*>(short*, short*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned short*>(unsigned short*, unsigned short*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, int*>(int*, int*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned*>(unsigned*, unsigned*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long*>(long*, long*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned long*>(unsigned long*, unsigned long*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long long*>(long long*, long long*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned long long*>(unsigned long long*, unsigned long long*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, float*>(float*, float*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, double*>(double*, double*, __less&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, long double*>(long double*, long double*, __less&); -extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); +#if _LIBCPP_STD_VER >= 20 +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} +#endif template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { std::__debug_randomize_range<_AlgPolicy>(__first, __last); - using _Comp_ref = __comp_ref_type<_Comp>; if (__libcpp_is_constant_evaluated()) { - std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp); - + std::__partial_sort<_AlgPolicy>( + std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__last), __comp); } else { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type; - _Comp_ref __comp_ref(__comp); - _WrappedComp __wrapped_comp(__comp_ref); - std::__sort<_WrappedComp>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __wrapped_comp); + std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); } + std::__check_strict_weak_ordering_sorted(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); } template @@ -709,7 +957,7 @@ void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __c template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::sort(__first, __last, __less::value_type>()); + std::sort(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/sort_heap.h b/lib/libcxx/include/__algorithm/sort_heap.h index 8249407b55..a82926ed1c 100644 --- a/lib/libcxx/include/__algorithm/sort_heap.h +++ b/lib/libcxx/include/__algorithm/sort_heap.h @@ -14,9 +14,11 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/pop_heap.h> #include <__config> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,11 +29,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { + _RandomAccessIterator __saved_last = __last; __comp_ref_type<_Compare> __comp_ref = __comp; using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n); + std::__check_strict_weak_ordering_sorted(__first, __saved_last, __comp_ref); } template @@ -46,8 +50,7 @@ void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::sort_heap(std::move(__first), std::move(__last), - __less::value_type>()); + std::sort_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/stable_partition.h b/lib/libcxx/include/__algorithm/stable_partition.h index a49de6dbb0..38fa9ce37d 100644 --- a/lib/libcxx/include/__algorithm/stable_partition.h +++ b/lib/libcxx/include/__algorithm/stable_partition.h @@ -21,7 +21,6 @@ #include <__utility/move.h> #include <__utility/pair.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -123,7 +122,10 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { - const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment + typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + + const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment // Either prove all true and return __first or point to first false while (true) { @@ -135,8 +137,6 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred } // We now have a reduced range [__first, __last) // *__first is known to be false - typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; - typedef typename iterator_traits<_ForwardIterator>::value_type value_type; difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); pair __p(0, 0); unique_ptr __h; diff --git a/lib/libcxx/include/__algorithm/stable_sort.h b/lib/libcxx/include/__algorithm/stable_sort.h index 8e70978ab6..dc24218b74 100644 --- a/lib/libcxx/include/__algorithm/stable_sort.h +++ b/lib/libcxx/include/__algorithm/stable_sort.h @@ -15,14 +15,15 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> #include <__memory/destruct_n.h> #include <__memory/temporary_buffer.h> #include <__memory/unique_ptr.h> +#include <__type_traits/is_trivially_copy_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,6 +31,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template +_LIBCPP_HIDE_FROM_ABI +void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, + typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + if (__first1 != __last1) { + __destruct_n __d(0); + unique_ptr __h(__first2, __d); + value_type* __last2 = __first2; + ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + for (++__last2; ++__first1 != __last1; ++__last2) { + value_type* __j2 = __last2; + value_type* __i2 = __j2; + if (__comp(*__first1, *--__i2)) { + ::new ((void*)__j2) value_type(std::move(*__i2)); + __d.template __incr(); + for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) + *__j2 = std::move(*__i2); + *__j2 = _Ops::__iter_move(__first1); + } else { + ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr(); + } + } + __h.release(); + } +} + template _LIBCPP_HIDE_FROM_ABI void __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, @@ -228,6 +260,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP } std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second); + std::__check_strict_weak_ordering_sorted(__first, __last, __comp); } template @@ -239,7 +272,7 @@ void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C template inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::stable_sort(__first, __last, __less::value_type>()); + std::stable_sort(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/three_way_comp_ref_type.h b/lib/libcxx/include/__algorithm/three_way_comp_ref_type.h new file mode 100644 index 0000000000..19c102f4c9 --- /dev/null +++ b/lib/libcxx/include/__algorithm/three_way_comp_ref_type.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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_THREE_WAY_COMP_REF_TYPE_H +#define _LIBCPP___ALGORITHM_THREE_WAY_COMP_REF_TYPE_H + +#include <__compare/ordering.h> +#include <__config> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template +struct __debug_three_way_comp { + _Comp& __comp_; + _LIBCPP_HIDE_FROM_ABI constexpr __debug_three_way_comp(_Comp& __c) : __comp_(__c) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(const _Tp& __x, const _Up& __y) { + auto __r = __comp_(__x, __y); + if constexpr (__comparison_category) + __do_compare_assert(__y, __x, __r); + return __r; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __x, _Up& __y) { + auto __r = __comp_(__x, __y); + if constexpr (__comparison_category) + __do_compare_assert(__y, __x, __r); + return __r; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr void __do_compare_assert(_LHS& __l, _RHS& __r, _Order __o) { + _Order __expected = __o; + if (__o == _Order::less) + __expected = _Order::greater; + if (__o == _Order::greater) + __expected = _Order::less; + _LIBCPP_ASSERT(__comp_(__l, __r) == __expected, "Comparator does not induce a strict weak ordering"); + (void)__l; + (void)__r; + } +}; + +// Pass the comparator by lvalue reference. Or in debug mode, using a +// debugging wrapper that stores a reference. +# if _LIBCPP_ENABLE_DEBUG_MODE +template +using __three_way_comp_ref_type = __debug_three_way_comp<_Comp>; +# else +template +using __three_way_comp_ref_type = _Comp&; +# endif + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_THREE_WAY_COMP_REF_TYPE_H diff --git a/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h index 1e86074b3d..1f2039949d 100644 --- a/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h +++ b/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h @@ -11,13 +11,13 @@ #include <__config> #include <__functional/invoke.h> -#include +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS #include <__undef_macros> @@ -57,6 +57,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H diff --git a/lib/libcxx/include/__algorithm/unwrap_iter.h b/lib/libcxx/include/__algorithm/unwrap_iter.h index 0f661e10a7..91346e3c1b 100644 --- a/lib/libcxx/include/__algorithm/unwrap_iter.h +++ b/lib/libcxx/include/__algorithm/unwrap_iter.h @@ -21,24 +21,27 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // TODO: Change the name of __unwrap_iter_impl to something more appropriate // The job of __unwrap_iter is to remove iterator wrappers (like reverse_iterator or __wrap_iter), // to reduce the number of template instantiations and to enable pointer-based optimizations e.g. in std::copy. -// In debug mode, we don't do this. // // Some algorithms (e.g. std::copy, but not std::sort) need to convert an // "unwrapped" result back into the original iterator type. Doing that is the job of __rewrap_iter. // Default case - we can't unwrap anything -template ::value> +template ::value> struct __unwrap_iter_impl { static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter, _Iter __iter) { return __iter; } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __unwrap(_Iter __i) _NOEXCEPT { return __i; } }; -#ifndef _LIBCPP_ENABLE_DEBUG_MODE +// TODO(hardening): make sure that the following unwrapping doesn't unexpectedly turn hardened iterators into raw +// pointers. // It's a contiguous iterator, so we can use a raw pointer instead template @@ -54,8 +57,6 @@ struct __unwrap_iter_impl<_Iter, true> { } }; -#endif // !_LIBCPP_ENABLE_DEBUG_MODE - template, __enable_if_t::value, int> = 0> @@ -64,6 +65,14 @@ decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXC return _Impl::__unwrap(__i); } +// Allow input_iterators to be passed to __unwrap_iter (but not __rewrap_iter) +#if _LIBCPP_STD_VER >= 20 +template ::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI constexpr _Iter __unwrap_iter(_Iter __i) noexcept { + return __i; +} +#endif + template > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig_iter, _Iter __iter) _NOEXCEPT { return _Impl::__rewrap(std::move(__orig_iter), std::move(__iter)); @@ -71,4 +80,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig _LIBCPP_END_NAMESPACE_STD +_LIBCPP_PUSH_MACROS + #endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H diff --git a/lib/libcxx/include/__algorithm/unwrap_range.h b/lib/libcxx/include/__algorithm/unwrap_range.h index 2c5d23e69f..2c75c8f49d 100644 --- a/lib/libcxx/include/__algorithm/unwrap_range.h +++ b/lib/libcxx/include/__algorithm/unwrap_range.h @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have // the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter. -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct __unwrap_range_impl { _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent) @@ -43,7 +43,7 @@ struct __unwrap_range_impl { } _LIBCPP_HIDE_FROM_ABI static constexpr auto - __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(std::move(__orig_iter))) __iter) requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> { return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); @@ -80,7 +80,7 @@ template < _LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter)); } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template ()))> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) { return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))); @@ -90,7 +90,7 @@ template 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/upper_bound.h b/lib/libcxx/include/__algorithm/upper_bound.h index 96552ce1f8..f499f7a80a 100644 --- a/lib/libcxx/include/__algorithm/upper_bound.h +++ b/lib/libcxx/include/__algorithm/upper_bound.h @@ -25,6 +25,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -47,8 +50,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { - static_assert(is_copy_constructible<_ForwardIterator>::value, - "Iterator has to be copy constructible"); + static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); return std::__upper_bound<_ClassicAlgPolicy>( std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity()); } @@ -56,13 +58,11 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu template _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::upper_bound( - std::move(__first), - std::move(__last), - __value, - __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); + return std::upper_bound(std::move(__first), std::move(__last), __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_UPPER_BOUND_H diff --git a/lib/libcxx/include/__assert b/lib/libcxx/include/__assert index 9c0cd1b119..d4af7e6c71 100644 --- a/lib/libcxx/include/__assert +++ b/lib/libcxx/include/__assert @@ -17,39 +17,21 @@ # pragma GCC system_header #endif -// TODO: Remove in LLVM 17. -#if defined(_LIBCPP_DEBUG) -# error "Defining _LIBCPP_DEBUG is not supported anymore. Please use _LIBCPP_ENABLE_DEBUG_MODE instead." -#endif +#define _LIBCPP_ASSERT(expression, message) \ + (__builtin_expect(static_cast(expression), 1) \ + ? (void)0 \ + : _LIBCPP_VERBOSE_ABORT( \ + "%s:%d: assertion %s failed: %s\n", __builtin_FILE(), __builtin_LINE(), #expression, message)) -// Automatically enable assertions when the debug mode is enabled. -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) -# ifndef _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ENABLE_ASSERTIONS 1 -# endif -#endif - -#ifndef _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ENABLE_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS_DEFAULT -#endif - -#if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 -# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" -#endif - -#if _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ASSERT(expression, message) \ - (__builtin_expect(static_cast(expression), 1) ? \ - (void)0 : \ - _LIBCPP_VERBOSE_ABORT("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) -#elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume) -# define _LIBCPP_ASSERT(expression, message) \ - (_LIBCPP_DIAGNOSTIC_PUSH \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \ - __builtin_assume(static_cast(expression)) \ - _LIBCPP_DIAGNOSTIC_POP) +// TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add +// assumptions without a clear optimization intent, disable that to avoid worsening the code generation. +// See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion. +#if 0 && __has_builtin(__builtin_assume) +# define _LIBCPP_ASSUME(expression) \ + (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \ + __builtin_assume(static_cast(expression)) _LIBCPP_DIAGNOSTIC_POP) #else -# define _LIBCPP_ASSERT(expression, message) ((void)0) +# define _LIBCPP_ASSUME(expression) ((void)0) #endif #endif // _LIBCPP___ASSERT diff --git a/lib/libcxx/include/__atomic/aliases.h b/lib/libcxx/include/__atomic/aliases.h new file mode 100644 index 0000000000..e2f9fae409 --- /dev/null +++ b/lib/libcxx/include/__atomic/aliases.h @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ALIASES_H +#define _LIBCPP___ATOMIC_ALIASES_H + +#include <__atomic/atomic.h> +#include <__atomic/atomic_lock_free.h> +#include <__atomic/contention_t.h> +#include <__atomic/is_always_lock_free.h> +#include <__config> +#include <__type_traits/conditional.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +using atomic_bool = atomic; +using atomic_char = atomic; +using atomic_schar = atomic; +using atomic_uchar = atomic; +using atomic_short = atomic; +using atomic_ushort = atomic; +using atomic_int = atomic; +using atomic_uint = atomic; +using atomic_long = atomic; +using atomic_ulong = atomic; +using atomic_llong = atomic; +using atomic_ullong = atomic; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +using atomic_char8_t = atomic; +#endif +using atomic_char16_t = atomic; +using atomic_char32_t = atomic; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using atomic_wchar_t = atomic; +#endif + +using atomic_int_least8_t = atomic; +using atomic_uint_least8_t = atomic; +using atomic_int_least16_t = atomic; +using atomic_uint_least16_t = atomic; +using atomic_int_least32_t = atomic; +using atomic_uint_least32_t = atomic; +using atomic_int_least64_t = atomic; +using atomic_uint_least64_t = atomic; + +using atomic_int_fast8_t = atomic; +using atomic_uint_fast8_t = atomic; +using atomic_int_fast16_t = atomic; +using atomic_uint_fast16_t = atomic; +using atomic_int_fast32_t = atomic; +using atomic_uint_fast32_t = atomic; +using atomic_int_fast64_t = atomic; +using atomic_uint_fast64_t = atomic; + +using atomic_int8_t = atomic< int8_t>; +using atomic_uint8_t = atomic; +using atomic_int16_t = atomic< int16_t>; +using atomic_uint16_t = atomic; +using atomic_int32_t = atomic< int32_t>; +using atomic_uint32_t = atomic; +using atomic_int64_t = atomic< int64_t>; +using atomic_uint64_t = atomic; + +using atomic_intptr_t = atomic; +using atomic_uintptr_t = atomic; +using atomic_size_t = atomic; +using atomic_ptrdiff_t = atomic; +using atomic_intmax_t = atomic; +using atomic_uintmax_t = atomic; + +// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type + +#if _LIBCPP_STD_VER >= 17 +# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value +#else +# define _LIBCPP_CONTENTION_LOCK_FREE false +#endif + +#if ATOMIC_LLONG_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long>; +using __libcpp_unsigned_lock_free = + __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long>; +#elif ATOMIC_INT_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int>; +#elif ATOMIC_SHORT_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short>; +#elif ATOMIC_CHAR_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>; +#else +// No signed/unsigned lock-free types +# define _LIBCPP_NO_LOCK_FREE_TYPES +#endif + +#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES) +using atomic_signed_lock_free = atomic<__libcpp_signed_lock_free>; +using atomic_unsigned_lock_free = atomic<__libcpp_unsigned_lock_free>; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ALIASES_H diff --git a/lib/libcxx/include/__atomic/atomic.h b/lib/libcxx/include/__atomic/atomic.h new file mode 100644 index 0000000000..68df7f12c1 --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic.h @@ -0,0 +1,664 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_H +#define _LIBCPP___ATOMIC_ATOMIC_H + +#include <__atomic/atomic_base.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_pointer.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct atomic + : public __atomic_base<_Tp> +{ + using __base = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI + atomic() = default; +#else + _LIBCPP_HIDE_FROM_ABI + atomic() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI + _Tp operator=(_Tp __d) volatile _NOEXCEPT + {__base::store(__d); return __d;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator=(_Tp __d) _NOEXCEPT + {__base::store(__d); return __d;} + + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; +}; + +// atomic + +template +struct atomic<_Tp*> + : public __atomic_base<_Tp*> +{ + using __base = __atomic_base<_Tp*>; + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI + atomic() _NOEXCEPT = default; + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI + _Tp* operator=(_Tp* __d) volatile _NOEXCEPT + {__base::store(__d); return __d;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator=(_Tp* __d) _NOEXCEPT + {__base::store(__d); return __d;} + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++(int) volatile _NOEXCEPT {return fetch_add(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++(int) _NOEXCEPT {return fetch_add(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--(int) volatile _NOEXCEPT {return fetch_sub(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--(int) _NOEXCEPT {return fetch_sub(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++() volatile _NOEXCEPT {return fetch_add(1) + 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++() _NOEXCEPT {return fetch_add(1) + 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--() volatile _NOEXCEPT {return fetch_sub(1) - 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--() _NOEXCEPT {return fetch_sub(1) - 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} + + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; +}; + +// atomic_is_lock_free + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->is_lock_free(); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->is_lock_free(); +} + +// atomic_init + +template +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI +void +atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); +} + +template +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI +void +atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); +} + +// atomic_store + +template +_LIBCPP_HIDE_FROM_ABI +void +atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + __o->store(__d); +} + +template +_LIBCPP_HIDE_FROM_ABI +void +atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + __o->store(__d); +} + +// atomic_store_explicit + +template +_LIBCPP_HIDE_FROM_ABI +void +atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) +{ + __o->store(__d, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +void +atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) +{ + __o->store(__d, __m); +} + +// atomic_load + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->load(); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load(const atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->load(); +} + +// atomic_load_explicit + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->load(__m); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->load(__m); +} + +// atomic_exchange + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->exchange(__d); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->exchange(__d); +} + +// atomic_exchange_explicit + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT +{ + return __o->exchange(__d, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT +{ + return __o->exchange(__d, __m); +} + +// atomic_compare_exchange_weak + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_weak(*__e, __d); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_weak(*__e, __d); +} + +// atomic_compare_exchange_strong + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_strong(*__e, __d); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_strong(*__e, __d); +} + +// atomic_compare_exchange_weak_explicit + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, + typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_weak(*__e, __d, __s, __f); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_weak(*__e, __d, __s, __f); +} + +// atomic_compare_exchange_strong_explicit + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_strong(*__e, __d, __s, __f); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, + typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_strong(*__e, __d, __s, __f); +} + +// atomic_wait + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait(const volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v) _NOEXCEPT +{ + return __o->wait(__v); +} + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait(const atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v) _NOEXCEPT +{ + return __o->wait(__v); +} + +// atomic_wait_explicit + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait_explicit(const volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v, + memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->wait(__v, __m); +} + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait_explicit(const atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v, + memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->wait(__v, __m); +} + +// atomic_notify_one + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_one(); +} +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +// atomic_notify_all + +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_all(); +} +template +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +// atomic_fetch_add + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_add(__op); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_add(__op); +} + +// atomic_fetch_add_explicit + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_add(__op, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_add(__op, __m); +} + +// atomic_fetch_sub + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_sub(__op); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_sub(__op); +} + +// atomic_fetch_sub_explicit + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_sub(__op, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_sub(__op, __m); +} + +// atomic_fetch_and + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_and(__op); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_and(__op); +} + +// atomic_fetch_and_explicit + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_and(__op, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_and(__op, __m); +} + +// atomic_fetch_or + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_or(__op); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_or(__op); +} + +// atomic_fetch_or_explicit + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_or(__op, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_or(__op, __m); +} + +// atomic_fetch_xor + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_xor(__op); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_xor(__op); +} + +// atomic_fetch_xor_explicit + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_xor(__op, __m); +} + +template +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_xor(__op, __m); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_H diff --git a/lib/libcxx/include/__atomic/atomic_base.h b/lib/libcxx/include/__atomic/atomic_base.h new file mode 100644 index 0000000000..87100ba5d8 --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic_base.h @@ -0,0 +1,232 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_BASE_H +#define _LIBCPP___ATOMIC_ATOMIC_BASE_H + +#include <__atomic/atomic_sync.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/is_always_lock_free.h> +#include <__atomic/memory_order.h> +#include <__availability> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_same.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template ::value && !is_same<_Tp, bool>::value> +struct __atomic_base // false +{ + mutable __cxx_atomic_impl<_Tp> __a_; + +#if _LIBCPP_STD_VER >= 17 + static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; +#endif + + _LIBCPP_HIDE_FROM_ABI + bool is_lock_free() const volatile _NOEXCEPT + {return __cxx_atomic_is_lock_free(sizeof(_Tp));} + _LIBCPP_HIDE_FROM_ABI + bool is_lock_free() const _NOEXCEPT + {return static_cast<__atomic_base const volatile*>(this)->is_lock_free();} + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI + operator _Tp() const volatile _NOEXCEPT {return load();} + _LIBCPP_HIDE_FROM_ABI + operator _Tp() const _NOEXCEPT {return load();} + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const + volatile _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr + __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} +#else + _LIBCPP_HIDE_FROM_ABI + __atomic_base() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} + + __atomic_base(const __atomic_base&) = delete; +}; + +#if _LIBCPP_STD_VER >= 17 +template +_LIBCPP_CONSTEXPR bool __atomic_base<_Tp, __b>::is_always_lock_free; +#endif + +// atomic + +template +struct __atomic_base<_Tp, true> + : public __atomic_base<_Tp, false> +{ + using __base = __atomic_base<_Tp, false>; + + _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) {} + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp operator++(int) volatile _NOEXCEPT {return fetch_add(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++(int) _NOEXCEPT {return fetch_add(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--(int) volatile _NOEXCEPT {return fetch_sub(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--(int) _NOEXCEPT {return fetch_sub(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++() volatile _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++() _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--() volatile _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--() _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator+=(_Tp __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator+=(_Tp __op) _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator-=(_Tp __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator-=(_Tp __op) _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator&=(_Tp __op) volatile _NOEXCEPT {return fetch_and(__op) & __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator&=(_Tp __op) _NOEXCEPT {return fetch_and(__op) & __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator|=(_Tp __op) volatile _NOEXCEPT {return fetch_or(__op) | __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator|=(_Tp __op) _NOEXCEPT {return fetch_or(__op) | __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator^=(_Tp __op) volatile _NOEXCEPT {return fetch_xor(__op) ^ __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator^=(_Tp __op) _NOEXCEPT {return fetch_xor(__op) ^ __op;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_BASE_H diff --git a/lib/libcxx/include/__atomic/atomic_flag.h b/lib/libcxx/include/__atomic/atomic_flag.h new file mode 100644 index 0000000000..edfa978f99 --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic_flag.h @@ -0,0 +1,230 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_FLAG_H +#define _LIBCPP___ATOMIC_ATOMIC_FLAG_H + +#include <__atomic/atomic_sync.h> +#include <__atomic/contention_t.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__chrono/duration.h> +#include <__config> +#include <__threading_support> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct atomic_flag +{ + __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_; + + _LIBCPP_HIDE_FROM_ABI + bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} + _LIBCPP_HIDE_FROM_ABI + bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} + + _LIBCPP_HIDE_FROM_ABI + bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} + _LIBCPP_HIDE_FROM_ABI + bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT + {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} + _LIBCPP_HIDE_FROM_ABI + void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} + _LIBCPP_HIDE_FROM_ABI + void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT + {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT + {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_one() volatile _NOEXCEPT + {__cxx_atomic_notify_one(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_one() _NOEXCEPT + {__cxx_atomic_notify_one(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_all() volatile _NOEXCEPT + {__cxx_atomic_notify_all(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_all() _NOEXCEPT + {__cxx_atomic_notify_all(&__a_);} + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr + atomic_flag() _NOEXCEPT : __a_(false) {} +#else + atomic_flag() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION + + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + +}; + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT +{ + return __o->test(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test(const atomic_flag* __o) _NOEXCEPT +{ + return __o->test(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT +{ + return __o->test_and_set(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT +{ + return __o->test_and_set(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test_and_set(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test_and_set(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->clear(); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear(atomic_flag* __o) _NOEXCEPT +{ + __o->clear(); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + __o->clear(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + __o->clear(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT +{ + __o->wait(__v); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT +{ + __o->wait(__v); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait_explicit(const volatile atomic_flag* __o, + bool __v, memory_order __m) _NOEXCEPT +{ + __o->wait(__v, __m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait_explicit(const atomic_flag* __o, + bool __v, memory_order __m) _NOEXCEPT +{ + __o->wait(__v, __m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H diff --git a/lib/libcxx/include/__atomic/atomic_init.h b/lib/libcxx/include/__atomic/atomic_init.h new file mode 100644 index 0000000000..14310aee10 --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic_init.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_INIT_H +#define _LIBCPP___ATOMIC_ATOMIC_INIT_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define ATOMIC_FLAG_INIT {false} +#define ATOMIC_VAR_INIT(__v) {__v} + +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1400 +# pragma clang deprecated(ATOMIC_VAR_INIT) +# endif +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) + +#endif // _LIBCPP___ATOMIC_ATOMIC_INIT_H diff --git a/lib/libcxx/include/__atomic/atomic_lock_free.h b/lib/libcxx/include/__atomic/atomic_lock_free.h new file mode 100644 index 0000000000..d607569ed0 --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic_lock_free.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_LOCK_FREE_H +#define _LIBCPP___ATOMIC_ATOMIC_LOCK_FREE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE) +# define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE +# define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE +#ifndef _LIBCPP_HAS_NO_CHAR8_T +# define ATOMIC_CHAR8_T_LOCK_FREE __CLANG_ATOMIC_CHAR8_T_LOCK_FREE +#endif +# define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE +# define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE +# define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE +# define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE +# define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE +# define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE +# define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE +# define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE +#elif defined(__GCC_ATOMIC_BOOL_LOCK_FREE) +# define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +# define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#ifndef _LIBCPP_HAS_NO_CHAR8_T +# define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +# define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +# define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +# define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +# define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +# define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +# define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +# define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +# define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +#endif // _LIBCPP___ATOMIC_ATOMIC_LOCK_FREE_H diff --git a/lib/libcxx/include/__atomic/atomic_sync.h b/lib/libcxx/include/__atomic/atomic_sync.h new file mode 100644 index 0000000000..d55450bb5f --- /dev/null +++ b/lib/libcxx/include/__atomic/atomic_sync.h @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_ATOMIC_SYNC_H +#define _LIBCPP___ATOMIC_ATOMIC_SYNC_H + +#include <__atomic/contention_t.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__availability> +#include <__chrono/duration.h> +#include <__config> +#include <__memory/addressof.h> +#include <__thread/poll_with_backoff.h> +#include <__threading_support> +#include <__type_traits/decay.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t); + +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t); + +template +struct __libcpp_atomic_wait_backoff_impl { + _Atp* __a; + _Fn __test_fn; + _LIBCPP_AVAILABILITY_SYNC + _LIBCPP_HIDE_FROM_ABI bool operator()(chrono::nanoseconds __elapsed) const + { + if(__elapsed > chrono::microseconds(64)) + { + auto const __monitor = std::__libcpp_atomic_monitor(__a); + if(__test_fn()) + return true; + std::__libcpp_atomic_wait(__a, __monitor); + } + else if(__elapsed > chrono::microseconds(4)) + __libcpp_thread_yield(); + else + {} // poll + return false; + } +}; + +template +_LIBCPP_AVAILABILITY_SYNC +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn) +{ + __libcpp_atomic_wait_backoff_impl<_Atp, __decay_t<_Fn> > __backoff_fn = {__a, __test_fn}; + return std::__libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); +} + +#else // _LIBCPP_HAS_NO_THREADS + +template +_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_impl<_Tp> const volatile*) { } +template +_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_impl<_Tp> const volatile*) { } +template +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp*, _Fn && __test_fn) +{ + return std::__libcpp_thread_poll_with_backoff(__test_fn, __spinning_backoff_policy()); +} + +#endif // _LIBCPP_HAS_NO_THREADS + +template _LIBCPP_HIDE_FROM_ABI +bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) { + return std::memcmp(std::addressof(__lhs), std::addressof(__rhs), sizeof(_Tp)) == 0; +} + +template +struct __cxx_atomic_wait_test_fn_impl { + _Atp* __a; + _Tp __val; + memory_order __order; + _LIBCPP_HIDE_FROM_ABI bool operator()() const + { + return !std::__cxx_nonatomic_compare_equal(std::__cxx_atomic_load(__a, __order), __val); + } +}; + +template +_LIBCPP_AVAILABILITY_SYNC +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order) +{ + __cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order}; + return std::__cxx_atomic_wait(__a, __test_fn); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_SYNC_H diff --git a/lib/libcxx/include/__atomic/check_memory_order.h b/lib/libcxx/include/__atomic/check_memory_order.h new file mode 100644 index 0000000000..d744312122 --- /dev/null +++ b/lib/libcxx/include/__atomic/check_memory_order.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_CHECK_MEMORY_ORDER_H +#define _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_consume || \ + __m == memory_order_acquire || \ + __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#define _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || \ + __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#define _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__m, __f) \ + _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || \ + __f == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#endif // _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H diff --git a/lib/libcxx/include/__atomic/contention_t.h b/lib/libcxx/include/__atomic/contention_t.h new file mode 100644 index 0000000000..1d8d02430b --- /dev/null +++ b/lib/libcxx/include/__atomic/contention_t.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_CONTENTION_T_H +#define _LIBCPP___ATOMIC_CONTENTION_T_H + +#include <__atomic/cxx_atomic_impl.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) + using __cxx_contention_t = int32_t; +#else + using __cxx_contention_t = int64_t; +#endif // __linux__ || (_AIX && !__64BIT__) + +using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_CONTENTION_T_H diff --git a/lib/libcxx/include/__atomic/cxx_atomic_impl.h b/lib/libcxx/include/__atomic/cxx_atomic_impl.h new file mode 100644 index 0000000000..167cee7f0b --- /dev/null +++ b/lib/libcxx/include/__atomic/cxx_atomic_impl.h @@ -0,0 +1,831 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_CXX_ATOMIC_IMPL_H +#define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H + +#include <__atomic/is_always_lock_free.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_const.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) || \ + defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) + +// [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because +// the default operator= in an object is not volatile, a byte-by-byte copy +// is required. +template _LIBCPP_HIDE_FROM_ABI +typename enable_if::value>::type +__cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { + __a_value = __val; +} +template _LIBCPP_HIDE_FROM_ABI +typename enable_if::value>::type +__cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { + volatile char* __to = reinterpret_cast(std::addressof(__a_value)); + volatile char* __end = __to + sizeof(_Tp); + volatile const char* __from = reinterpret_cast(std::addressof(__val)); + while (__to != __end) + *__to++ = *__from++; +} + +#endif + +#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) + +template +struct __cxx_atomic_base_impl { + + _LIBCPP_HIDE_FROM_ABI +#ifndef _LIBCPP_CXX03_LANG + __cxx_atomic_base_impl() _NOEXCEPT = default; +#else + __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT + : __a_value(value) {} + _Tp __a_value; +}; + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed ? __ATOMIC_RELAXED: + (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: + (__order == memory_order_release ? __ATOMIC_RELEASE: + (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: + (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL: + __ATOMIC_CONSUME)))); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed ? __ATOMIC_RELAXED: + (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: + (__order == memory_order_release ? __ATOMIC_RELAXED: + (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: + (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE: + __ATOMIC_CONSUME)))); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { + __cxx_atomic_assign_volatile(__a->__a_value, __val); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { + __a->__a_value = __val; +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_thread_fence(memory_order __order) { + __atomic_thread_fence(__to_gcc_order(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_signal_fence(memory_order __order) { + __atomic_signal_fence(__to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, + memory_order __order) { + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, + memory_order __order) { + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, + memory_order __order) { + _Tp __ret; + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { + _Tp __ret; + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __value, memory_order __order) { + _Tp __ret; + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, + memory_order __order) { + _Tp __ret; + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong( + volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, + memory_order __success, memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong( + __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, + memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak( + volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, + memory_order __success, memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak( + __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, + memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template +struct __skip_amt { enum {value = 1}; }; + +template +struct __skip_amt<_Tp*> { enum {value = sizeof(_Tp)}; }; + +// FIXME: Haven't figured out what the spec says about using arrays with +// atomic_fetch_add. Force a failure rather than creating bad behavior. +template +struct __skip_amt<_Tp[]> { }; +template +struct __skip_amt<_Tp[n]> { }; + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Td __delta, memory_order __order) { + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, + memory_order __order) { + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Td __delta, memory_order __order) { + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, + memory_order __order) { + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, + memory_order __order) { + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, + memory_order __order) { + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +#define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) + +#elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) + +template +struct __cxx_atomic_base_impl { + + _LIBCPP_HIDE_FROM_ABI +#ifndef _LIBCPP_CXX03_LANG + __cxx_atomic_base_impl() _NOEXCEPT = default; +#else + __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} +#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; +}; + +#define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { + __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { + __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { + __c11_atomic_init(std::addressof(__a->__a_value), __val); +} +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val) _NOEXCEPT { + __c11_atomic_init(std::addressof(__a->__a_value), __val); +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val, memory_order __order) _NOEXCEPT { + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { + using __ptr_type = __remove_const_t__a_value)>*; + return __c11_atomic_load( + const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { + using __ptr_type = __remove_const_t__a_value)>*; + return __c11_atomic_load( + const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { + return __c11_atomic_exchange( + std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory_order __order) _NOEXCEPT { + return __c11_atomic_exchange( + std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_release ? memory_order_relaxed: + (__order == memory_order_acq_rel ? memory_order_acquire: + __order); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +#endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP + +#ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS + +template +struct __cxx_atomic_lock_impl { + + _LIBCPP_HIDE_FROM_ABI + __cxx_atomic_lock_impl() _NOEXCEPT + : __a_value(), __a_lock(0) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit + __cxx_atomic_lock_impl(_Tp value) _NOEXCEPT + : __a_value(value), __a_lock(0) {} + + _Tp __a_value; + mutable __cxx_atomic_base_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_lock; + + _LIBCPP_HIDE_FROM_ABI void __lock() const volatile { + while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) + /*spin*/; + } + _LIBCPP_HIDE_FROM_ABI void __lock() const { + while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) + /*spin*/; + } + _LIBCPP_HIDE_FROM_ABI void __unlock() const volatile { + __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); + } + _LIBCPP_HIDE_FROM_ABI void __unlock() const { + __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); + } + _LIBCPP_HIDE_FROM_ABI _Tp __read() const volatile { + __lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a_value); + __unlock(); + return __old; + } + _LIBCPP_HIDE_FROM_ABI _Tp __read() const { + __lock(); + _Tp __old = __a_value; + __unlock(); + return __old; + } +}; + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { + __cxx_atomic_assign_volatile(__a->__a_value, __val); +} +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { + __a->__a_value = __val; +} + +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { + __a->__lock(); + __cxx_atomic_assign_volatile(__a->__a_value, __val); + __a->__unlock(); +} +template +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { + __a->__lock(); + __a->__a_value = __val; + __a->__unlock(); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const volatile __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { + return __a->__read(); +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { + return __a->__read(); +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, __value); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value = __value; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + _Tp __temp; + __a->__lock(); + __cxx_atomic_assign_volatile(__temp, __a->__a_value); + bool __ret = (std::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); + if(__ret) + __cxx_atomic_assign_volatile(__a->__a_value, __value); + else + __cxx_atomic_assign_volatile(*__expected, __a->__a_value); + __a->__unlock(); + return __ret; +} +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + __a->__lock(); + bool __ret = (std::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); + if(__ret) + std::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); + else + std::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); + __a->__unlock(); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + _Tp __temp; + __a->__lock(); + __cxx_atomic_assign_volatile(__temp, __a->__a_value); + bool __ret = (std::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); + if(__ret) + __cxx_atomic_assign_volatile(__a->__a_value, __value); + else + __cxx_atomic_assign_volatile(*__expected, __a->__a_value); + __a->__unlock(); + return __ret; +} +template +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + __a->__lock(); + bool __ret = (std::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); + if(__ret) + std::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); + else + std::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); + __a->__unlock(); + return __ret; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old + __delta)); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value += __delta; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp*>* __a, + ptrdiff_t __delta, memory_order) { + __a->__lock(); + _Tp* __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, __old + __delta); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp*>* __a, + ptrdiff_t __delta, memory_order) { + __a->__lock(); + _Tp* __old = __a->__a_value; + __a->__a_value += __delta; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old - __delta)); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value -= __delta; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old & __pattern)); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value &= __pattern; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old | __pattern)); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value |= __pattern; + __a->__unlock(); + return __old; +} + +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old ^ __pattern)); + __a->__unlock(); + return __old; +} +template +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value ^= __pattern; + __a->__unlock(); + return __old; +} + +template ::__value, + __cxx_atomic_base_impl<_Tp>, + __cxx_atomic_lock_impl<_Tp> >::type> +#else +template > +#endif //_LIBCPP_ATOMIC_ONLY_USE_BUILTINS +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) {} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H diff --git a/lib/libcxx/include/__atomic/fence.h b/lib/libcxx/include/__atomic/fence.h new file mode 100644 index 0000000000..c62f38f211 --- /dev/null +++ b/lib/libcxx/include/__atomic/fence.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_FENCE_H +#define _LIBCPP___ATOMIC_FENCE_H + +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_thread_fence(memory_order __m) _NOEXCEPT +{ + __cxx_atomic_thread_fence(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_signal_fence(memory_order __m) _NOEXCEPT +{ + __cxx_atomic_signal_fence(__m); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_FENCE_H diff --git a/lib/libcxx/include/__atomic/is_always_lock_free.h b/lib/libcxx/include/__atomic/is_always_lock_free.h new file mode 100644 index 0000000000..fbbd437074 --- /dev/null +++ b/lib/libcxx/include/__atomic/is_always_lock_free.h @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_IS_ALWAYS_LOCK_FREE_H +#define _LIBCPP___ATOMIC_IS_ALWAYS_LOCK_FREE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __libcpp_is_always_lock_free { + // __atomic_always_lock_free is available in all Standard modes + static const bool __value = __atomic_always_lock_free(sizeof(_Tp), 0); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_IS_ALWAYS_LOCK_FREE_H diff --git a/lib/libcxx/include/__atomic/kill_dependency.h b/lib/libcxx/include/__atomic/kill_dependency.h new file mode 100644 index 0000000000..1bd5c8ca76 --- /dev/null +++ b/lib/libcxx/include/__atomic/kill_dependency.h @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_KILL_DEPENDENCY_H +#define _LIBCPP___ATOMIC_KILL_DEPENDENCY_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI +_Tp kill_dependency(_Tp __y) _NOEXCEPT +{ + return __y; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_KILL_DEPENDENCY_H diff --git a/lib/libcxx/include/__atomic/memory_order.h b/lib/libcxx/include/__atomic/memory_order.h new file mode 100644 index 0000000000..3671dc3cf9 --- /dev/null +++ b/lib/libcxx/include/__atomic/memory_order.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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___ATOMIC_MEMORY_ORDER_H +#define _LIBCPP___ATOMIC_MEMORY_ORDER_H + +#include <__config> +#include <__type_traits/is_same.h> +#include <__type_traits/underlying_type.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Figure out what the underlying type for `memory_order` would be if it were +// declared as an unscoped enum (accounting for -fshort-enums). Use this result +// 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 = underlying_type<__legacy_memory_order>::type; + +#if _LIBCPP_STD_VER >= 20 + +enum class memory_order : __memory_order_underlying_t { + relaxed = __mo_relaxed, + consume = __mo_consume, + acquire = __mo_acquire, + release = __mo_release, + acq_rel = __mo_acq_rel, + seq_cst = __mo_seq_cst +}; + +static_assert((is_same::type, __memory_order_underlying_t>::value), + "unexpected underlying type for std::memory_order"); + +inline constexpr auto memory_order_relaxed = memory_order::relaxed; +inline constexpr auto memory_order_consume = memory_order::consume; +inline constexpr auto memory_order_acquire = memory_order::acquire; +inline constexpr auto memory_order_release = memory_order::release; +inline constexpr auto memory_order_acq_rel = memory_order::acq_rel; +inline constexpr auto memory_order_seq_cst = memory_order::seq_cst; + +#else + +enum memory_order { + memory_order_relaxed = __mo_relaxed, + memory_order_consume = __mo_consume, + memory_order_acquire = __mo_acquire, + memory_order_release = __mo_release, + memory_order_acq_rel = __mo_acq_rel, + memory_order_seq_cst = __mo_seq_cst, +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_MEMORY_ORDER_H diff --git a/lib/libcxx/include/__availability b/lib/libcxx/include/__availability index 6dfca3fa8b..7807f22b71 100644 --- a/lib/libcxx/include/__availability +++ b/lib/libcxx/include/__availability @@ -39,17 +39,23 @@ // // This mechanism is general in nature, and any vendor can add their markup to // the library (see below). Whenever a new feature is added that requires support -// in the shared library, a macro should be added below to mark this feature -// as unavailable. When vendors decide to ship the feature as part of their -// shared library, they can update the markup appropriately. +// in the shared library, two macros are added below to allow marking the feature +// as unavailable: +// 1. A macro named `_LIBCPP_AVAILABILITY_HAS_NO_` which must be defined +// exactly when compiling for a target that doesn't support the feature. +// 2. A macro named `_LIBCPP_AVAILABILITY_`, which must always be defined +// and must expand to the proper availability attribute for the platform. +// +// When vendors decide to ship the feature as part of their shared library, they +// can update these macros appropriately for their platform, and the library will +// use those to provide an optimal user experience. // // Furthermore, many features in the standard library have corresponding -// feature-test macros. When a feature is made unavailable on some deployment -// target, a macro should be defined to signal that it is unavailable. That -// macro can then be picked up when feature-test macros are generated (see -// generate_feature_test_macro_components.py) to make sure that feature-test -// macros don't announce a feature as being implemented if it has been marked -// as unavailable. +// feature-test macros. The `_LIBCPP_AVAILABILITY_HAS_NO_` macros +// are checked by the corresponding feature-test macros generated by +// generate_feature_test_macro_components.py to ensure that the library +// doesn't announce a feature as being implemented if it is unavailable on +// the deployment target. // // Note that this mechanism is disabled by default in the "upstream" libc++. // Availability annotations are only meaningful when shipping libc++ inside @@ -83,9 +89,8 @@ // This controls the availability of std::shared_mutex and std::shared_timed_mutex, // which were added to the dylib later. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX # define _LIBCPP_AVAILABILITY_SHARED_MUTEX -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex // These macros control the availability of std::bad_optional_access and // other exception types. These were put in the shared library to prevent @@ -95,16 +100,23 @@ // 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_NO_BAD_OPTIONAL_ACCESS # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + +// # define _LIBCPP_AVAILABILITY_HAS_NO_BAD_VARIANT_ACCESS # define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS + +// # define _LIBCPP_AVAILABILITY_HAS_NO_BAD_ANY_CAST # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST // This controls the availability of std::uncaught_exceptions(). +// # define _LIBCPP_AVAILABILITY_HAS_NO_UNCAUGHT_EXCEPTIONS # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS // This controls the availability of the sized version of ::operator delete, // ::operator delete[], and their align_val_t variants, which were all added // in C++17, and hence not present in early dylibs. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SIZED_NEW_DELETE # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE // This controls the availability of the std::future_error exception. @@ -112,73 +124,83 @@ // Note that when exceptions are disabled, the methods that normally throw // std::future_error can be used even on older deployment targets, but those // methods will abort instead of throwing. +// # define _LIBCPP_AVAILABILITY_HAS_NO_FUTURE_ERROR # define _LIBCPP_AVAILABILITY_FUTURE_ERROR // This controls the availability of std::type_info's vtable. // I can't imagine how using std::type_info can work at all if // this isn't supported. +// # define _LIBCPP_AVAILABILITY_HAS_NO_TYPEINFO_VTABLE # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE // This controls the availability of std::locale::category members // (e.g. std::locale::collate), which are defined in the dylib. +// # define _LIBCPP_AVAILABILITY_HAS_NO_LOCALE_CATEGORY # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY // This controls the availability of atomic operations on std::shared_ptr // (e.g. `std::atomic_store(std::shared_ptr)`), which require a shared // lock table located in the dylib. +// # define _LIBCPP_AVAILABILITY_HAS_NO_ATOMIC_SHARED_PTR # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR // These macros control the availability of all parts of that // depend on something in the dylib. -# define _LIBCPP_AVAILABILITY_FILESYSTEM -# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH -# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem +// # define _LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP // This controls the availability of floating-point std::to_chars functions. // These overloads were added later than the integer overloads. +// # define _LIBCPP_AVAILABILITY_HAS_NO_TO_CHARS_FLOATING_POINT # define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT // This controls the availability of the C++20 synchronization library, // which requires shared library support for various operations // (see libcxx/src/atomic.cpp). This includes , , // , and notification functions on std::atomic. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SYNC # define _LIBCPP_AVAILABILITY_SYNC -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore - - // This controls the availability of the C++20 format library. - // The library is in development and not ABI stable yet. P2216 is - // retroactively accepted in C++20. This paper contains ABI breaking - // changes. -# define _LIBCPP_AVAILABILITY_FORMAT -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format // This controls whether the library claims to provide a default verbose // termination function, and consequently whether the headers will try // to use it when the mechanism isn't overriden at compile-time. -// # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY +// # define _LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT +# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT + + // This controls the availability of the C++17 std::pmr library, + // which is implemented in large part in the built library. +// # define _LIBCPP_AVAILABILITY_HAS_NO_PMR +# define _LIBCPP_AVAILABILITY_PMR #elif defined(__APPLE__) + // shared_mutex and shared_timed_mutex +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX +# endif # define _LIBCPP_AVAILABILITY_SHARED_MUTEX \ __attribute__((availability(macos,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex -# endif + // bad_optional_access, bad_variant_access and bad_any_cast // Note: bad_optional_access & friends were not introduced in the matching // macOS and iOS versions, so the version mismatch between macOS and others // is intended. +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_VARIANT_ACCESS +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_ANY_CAST +# endif # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ __attribute__((availability(macos,strict,introduced=10.13))) \ __attribute__((availability(ios,strict,introduced=12.0))) \ @@ -189,78 +211,142 @@ # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \ _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + // uncaught_exceptions +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_HAS_NO_UNCAUGHT_EXCEPTIONS +# endif # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \ __attribute__((availability(macos,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + // sized operator new and sized operator delete +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_HAS_NO_SIZED_NEW_DELETE +# endif # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \ __attribute__((availability(macos,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + // future_error +# if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_AVAILABILITY_HAS_NO_FUTURE_ERROR +# endif # define _LIBCPP_AVAILABILITY_FUTURE_ERROR \ __attribute__((availability(ios,strict,introduced=6.0))) + // type_info's vtable +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_TYPEINFO_VTABLE +# endif # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + // locale::category +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_LOCALE_CATEGORY +# endif # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + // atomic operations on shared_ptr +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_ATOMIC_SHARED_PTR +# endif # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) -# define _LIBCPP_AVAILABILITY_FILESYSTEM \ - __attribute__((availability(macos,strict,introduced=10.15))) \ - __attribute__((availability(ios,strict,introduced=13.0))) \ - __attribute__((availability(tvos,strict,introduced=13.0))) \ - __attribute__((availability(watchos,strict,introduced=6.0))) -# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH \ - _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") -# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") + // # 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) || \ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem +# define _LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY # endif +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY \ + __attribute__((availability(macos,strict,introduced=10.15))) \ + __attribute__((availability(ios,strict,introduced=13.0))) \ + __attribute__((availability(tvos,strict,introduced=13.0))) \ + __attribute__((availability(watchos,strict,introduced=6.0))) +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH \ + _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") + // std::to_chars(floating-point) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 130300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 160300) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 160300) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 90300) +# define _LIBCPP_AVAILABILITY_HAS_NO_TO_CHARS_FLOATING_POINT +# endif # define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT \ - __attribute__((unavailable)) + __attribute__((availability(macos,strict,introduced=13.3))) \ + __attribute__((availability(ios,strict,introduced=16.3))) \ + __attribute__((availability(tvos,strict,introduced=16.3))) \ + __attribute__((availability(watchos,strict,introduced=9.3))) + // c++20 synchronization library +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_SYNC +# endif # define _LIBCPP_AVAILABILITY_SYNC \ __attribute__((availability(macos,strict,introduced=11.0))) \ __attribute__((availability(ios,strict,introduced=14.0))) \ __attribute__((availability(tvos,strict,introduced=14.0))) \ __attribute__((availability(watchos,strict,introduced=7.0))) -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore + + // __libcpp_verbose_abort +# if 1 // TODO: Update once this is released +# define _LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT # endif - -# define _LIBCPP_AVAILABILITY_FORMAT \ +# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT \ __attribute__((unavailable)) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format -# define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + // std::pmr +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 100000) +# define _LIBCPP_AVAILABILITY_HAS_NO_PMR +# endif +// TODO: Enable std::pmr markup once https://github.com/llvm/llvm-project/issues/40340 has been fixed +// Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support +// it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we +// use availability annotations until that bug has been fixed. +# if 0 +# define _LIBCPP_AVAILABILITY_PMR \ + __attribute__((availability(macos, strict, introduced = 14.0))) \ + __attribute__((availability(ios, strict, introduced = 17.0))) \ + __attribute__((availability(tvos, strict, introduced = 17.0))) \ + __attribute__((availability(watchos, strict, introduced = 10.0))) +# else +# define _LIBCPP_AVAILABILITY_PMR +# endif #else @@ -270,10 +356,10 @@ #endif -// Define availability attributes that depend on _LIBCPP_NO_EXCEPTIONS. +// Define availability attributes that depend on _LIBCPP_HAS_NO_EXCEPTIONS. // Those are defined in terms of the availability attributes above, and // should not be vendor-specific. -#if defined(_LIBCPP_NO_EXCEPTIONS) +#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) # define _LIBCPP_AVAILABILITY_FUTURE # define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST # define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS diff --git a/lib/libcxx/include/__bit/bit_cast.h b/lib/libcxx/include/__bit/bit_cast.h index 2ca4120c76..39842465e1 100644 --- a/lib/libcxx/include/__bit/bit_cast.h +++ b/lib/libcxx/include/__bit/bit_cast.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template requires(sizeof(_ToType) == sizeof(_FromType) && @@ -29,7 +29,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _Fr return __builtin_bit_cast(_ToType, __from); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__bit/bit_ceil.h b/lib/libcxx/include/__bit/bit_ceil.h index a558d61942..706d446359 100644 --- a/lib/libcxx/include/__bit/bit_ceil.h +++ b/lib/libcxx/include/__bit/bit_ceil.h @@ -24,18 +24,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); - _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); if constexpr (sizeof(_Tp) >= sizeof(unsigned)) return _Tp{1} << __n; else { const unsigned __extra = numeric_limits::digits - numeric_limits<_Tp>::digits; - const unsigned __retVal = 1u << (__n + __extra); - return (_Tp)(__retVal >> __extra); + const unsigned __ret_val = 1u << (__n + __extra); + return (_Tp)(__ret_val >> __extra); } } diff --git a/lib/libcxx/include/__bit/bit_floor.h b/lib/libcxx/include/__bit/bit_floor.h index b2e38092f2..cf5cf5803a 100644 --- a/lib/libcxx/include/__bit/bit_floor.h +++ b/lib/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _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_width.h b/lib/libcxx/include/__bit/bit_width.h index 4381f227f5..a2020a0142 100644 --- a/lib/libcxx/include/__bit/bit_width.h +++ b/lib/libcxx/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _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/byteswap.h b/lib/libcxx/include/__bit/byteswap.h index 6fa8d48baf..a1e1b53097 100644 --- a/lib/libcxx/include/__bit/byteswap.h +++ b/lib/libcxx/include/__bit/byteswap.h @@ -13,7 +13,6 @@ #include <__concepts/arithmetic.h> #include <__config> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,10 +20,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template -_LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; @@ -48,7 +47,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { } } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__bit/countl.h b/lib/libcxx/include/__bit/countl.h index 86eaee0c1b..5d5744ac9a 100644 --- a/lib/libcxx/include/__bit/countl.h +++ b/lib/libcxx/include/__bit/countl.h @@ -24,13 +24,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } # ifndef _LIBCPP_HAS_NO_INT128 @@ -86,12 +86,12 @@ int __countl_zero(_Tp __t) _NOEXCEPT #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _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 d3ca5b6c94..66ca5e7e66 100644 --- a/lib/libcxx/include/__bit/countr.h +++ b/lib/libcxx/include/__bit/countr.h @@ -23,19 +23,19 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { if (__t == 0) return numeric_limits<_Tp>::digits; @@ -57,7 +57,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _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 b89f5995b3..a4e178060a 100644 --- a/lib/libcxx/include/__bit/has_single_bit.h +++ b/lib/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _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 33b94cff71..62f4786bce 100644 --- a/lib/libcxx/include/__bit/popcount.h +++ b/lib/libcxx/include/__bit/popcount.h @@ -35,7 +35,7 @@ int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popco #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { if (sizeof(_Tp) <= sizeof(unsigned int)) return std::__libcpp_popcount(static_cast(__t)); else if (sizeof(_Tp) <= sizeof(unsigned long)) diff --git a/lib/libcxx/include/__bit/rotate.h b/lib/libcxx/include/__bit/rotate.h index 5aa7518b3c..e9f4c8d474 100644 --- a/lib/libcxx/include/__bit/rotate.h +++ b/lib/libcxx/include/__bit/rotate.h @@ -34,7 +34,7 @@ _Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { const unsigned int __dig = numeric_limits<_Tp>::digits; if ((__cnt % __dig) == 0) return __t; @@ -42,7 +42,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { return std::__rotr(__t, __cnt); } diff --git a/lib/libcxx/include/__bit_reference b/lib/libcxx/include/__bit_reference index 2665749139..a6bb6d4250 100644 --- a/lib/libcxx/include/__bit_reference +++ b/lib/libcxx/include/__bit_reference @@ -19,8 +19,9 @@ #include <__iterator/iterator_traits.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> +#include <__type_traits/conditional.h> +#include <__utility/swap.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -75,7 +76,7 @@ public: return *this; } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { if (__x) *__seg_ |= __mask_; @@ -155,6 +156,8 @@ class __bit_const_reference friend typename _Cp::__self; friend class __bit_iterator<_Cp, true>; public: + using __container = typename _Cp::__self; + _LIBCPP_INLINE_VISIBILITY __bit_const_reference(const __bit_const_reference&) = default; @@ -728,12 +731,12 @@ move_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCons // swap_ranges -template -_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> -__swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, - __bit_iterator<__C2, false> __result) +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) { - typedef __bit_iterator<__C1, false> _I1; + typedef __bit_iterator<_Cl, false> _I1; typedef typename _I1::difference_type difference_type; typedef typename _I1::__storage_type __storage_type; const int __bits_per_word = _I1::__bits_per_word; @@ -778,12 +781,12 @@ __swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, return __result; } -template -_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> -__swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, - __bit_iterator<__C2, false> __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) { - typedef __bit_iterator<__C1, false> _I1; + typedef __bit_iterator<_Cl, false> _I1; typedef typename _I1::difference_type difference_type; typedef typename _I1::__storage_type __storage_type; const int __bits_per_word = _I1::__bits_per_word; @@ -878,11 +881,11 @@ __swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1 return __result; } -template +template inline _LIBCPP_INLINE_VISIBILITY -__bit_iterator<__C2, false> -swap_ranges(__bit_iterator<__C1, false> __first1, __bit_iterator<__C1, false> __last1, - __bit_iterator<__C2, false> __first2) +__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 _VSTD::__swap_ranges_aligned(__first1, __last1, __first2); @@ -1135,7 +1138,7 @@ private: public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 : __seg_(nullptr), __ctz_(0) #endif {} @@ -1311,15 +1314,15 @@ private: friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); - template friend __bit_iterator<__C2, false> __swap_ranges_unaligned(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); - template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); + template 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> __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>, diff --git a/lib/libcxx/include/__charconv/chars_format.h b/lib/libcxx/include/__charconv/chars_format.h index 695bd87318..0e781c047e 100644 --- a/lib/libcxx/include/__charconv/chars_format.h +++ b/lib/libcxx/include/__charconv/chars_format.h @@ -19,58 +19,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -enum class _LIBCPP_ENUM_VIS chars_format -{ - scientific = 0x1, - fixed = 0x2, - hex = 0x4, - general = fixed | scientific -}; +enum class _LIBCPP_ENUM_VIS chars_format { scientific = 0x1, fixed = 0x2, hex = 0x4, general = fixed | scientific }; -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator~(chars_format __x) { - return chars_format(~_VSTD::__to_underlying(__x)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator~(chars_format __x) { + return chars_format(~std::__to_underlying(__x)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator&(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) & - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator&(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) & std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator|(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) | - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator|(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) | std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator^(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) ^ - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator^(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) ^ std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator&=(chars_format& __x, chars_format __y) { __x = __x & __y; return __x; } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator|=(chars_format& __x, chars_format __y) { __x = __x | __y; return __x; } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator^=(chars_format& __x, chars_format __y) { __x = __x ^ __y; return __x; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__charconv/from_chars_integral.h b/lib/libcxx/include/__charconv/from_chars_integral.h new file mode 100644 index 0000000000..acfdf4b30d --- /dev/null +++ b/lib/libcxx/include/__charconv/from_chars_integral.h @@ -0,0 +1,239 @@ +// -*- 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___CHARCONV_FROM_CHARS_INTEGRAL_H +#define _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H + +#include <__algorithm/copy_n.h> +#include <__charconv/from_chars_result.h> +#include <__charconv/traits.h> +#include <__config> +#include <__memory/addressof.h> +#include <__system_error/errc.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_unsigned.h> +#include <__type_traits/make_unsigned.h> +#include + +#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 + +from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete; + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) { + using __tl = numeric_limits<_Tp>; + decltype(std::__to_unsigned_like(__value)) __x; + + bool __neg = (__first != __last && *__first == '-'); + auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); + switch (__r.ec) { + case errc::invalid_argument: + return {__first, __r.ec}; + case errc::result_out_of_range: + return __r; + default: + break; + } + + if (__neg) { + if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) { + __x = std::__complement(__x); + std::copy_n(std::addressof(__x), 1, std::addressof(__value)); + return __r; + } + } else { + if (__x <= std::__to_unsigned_like(__tl::max())) { + __value = __x; + return __r; + } + } + + return {__r.ptr, errc::result_out_of_range}; +} + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __in_pattern(_Tp __c) { + return '0' <= __c && __c <= '9'; +} + +struct _LIBCPP_HIDDEN __in_pattern_result { + bool __ok; + int __val; + + explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; } +}; + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result __in_pattern(_Tp __c, int __base) { + if (__base <= 10) + return {'0' <= __c && __c < '0' + __base, __c - '0'}; + else if (std::__in_pattern(__c)) + return {true, __c - '0'}; + else if ('a' <= __c && __c < 'a' + __base - 10) + return {true, __c - 'a' + 10}; + else + return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10}; +} + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) { + auto __find_non_zero = [](_It __firstit, _It __lastit) { + for (; __firstit != __lastit; ++__firstit) + if (*__firstit != '0') + break; + return __firstit; + }; + + auto __p = __find_non_zero(__first, __last); + if (__p == __last || !std::__in_pattern(*__p, __args...)) { + if (__p == __first) + return {__first, errc::invalid_argument}; + else { + __value = 0; + return {__p, {}}; + } + } + + auto __r = __f(__p, __last, __value, __args...); + if (__r.ec == errc::result_out_of_range) { + for (; __r.ptr != __last; ++__r.ptr) { + if (!std::__in_pattern(*__r.ptr, __args...)) + break; + } + } + + return __r; +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) { + using __tx = __itoa::__traits<_Tp>; + using __output_type = typename __tx::type; + + return std::__subject_seq_combinator( + __first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result { + __output_type __a, __b; + auto __p = __tx::__read(__f, __l, __a, __b); + if (__p == __l || !std::__in_pattern(*__p)) { + __output_type __m = numeric_limits<_Tp>::max(); + if (__m >= __a && __m - __a >= __b) { + __val = __a + __b; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }); +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) { + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); +} + +/* +// Code used to generate __from_chars_log2f_lut. +#include +#include +#include + +int main() { + for (int i = 2; i <= 36; ++i) + std::cout << std::format("{},\n", log2f(i)); +} +*/ +/// log2f table for bases [2, 36]. +inline constexpr float __from_chars_log2f_lut[35] = { + 1, 1.5849625, 2, 2.321928, 2.5849626, 2.807355, 3, 3.169925, 3.321928, + 3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4, 4.087463, 4.169925, 4.2479277, + 4.321928, 4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044, 4.7548876, 4.807355, + 4.857981, 4.9068904, 4.9541965, 5, 5.044394, 5.087463, 5.129283, 5.169925}; + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { + if (__base == 10) + return std::__from_chars_atoi(__first, __last, __value); + + return std::__subject_seq_combinator( + __first, + __last, + __value, + [](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result { + using __tl = numeric_limits<_Tp>; + // __base is always between 2 and 36 inclusive. + auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2]; + _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0; + + for (int __i = 1; __p != __lastp; ++__i, ++__p) { + if (auto __c = __in_pattern(*__p, __b)) { + if (__i < __digits - 1) + __x = __x * __b + __c.__val; + else { + if (!__itoa::__mul_overflowed(__x, __b, __x)) + ++__p; + __y = __c.__val; + break; + } + } else + break; + } + + if (__p == __lastp || !__in_pattern(*__p, __b)) { + if (__tl::max() - __x >= __y) { + __val = __x + __y; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }, + __base); +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, __from_chars_integral<__t>, __base); +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value) { + return std::__from_chars_atoi(__first, __last, __value); +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value, int __base) { + _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]"); + return std::__from_chars_integral(__first, __last, __value, __base); +} +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H diff --git a/lib/libcxx/include/__charconv/from_chars_result.h b/lib/libcxx/include/__charconv/from_chars_result.h index 05ffe1485c..fa98616a0c 100644 --- a/lib/libcxx/include/__charconv/from_chars_result.h +++ b/lib/libcxx/include/__charconv/from_chars_result.h @@ -11,7 +11,7 @@ #define _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H #include <__config> -#include <__errc> +#include <__system_error/errc.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,18 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -struct _LIBCPP_TYPE_VIS from_chars_result -{ - const char* ptr; - errc ec; -# if _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const from_chars_result&, const from_chars_result&) = default; +struct _LIBCPP_EXPORTED_FROM_ABI from_chars_result { + const char* ptr; + errc ec; +# if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const from_chars_result&, const from_chars_result&) = default; # endif }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__charconv/tables.h b/lib/libcxx/include/__charconv/tables.h index 9b82440348..6b93536b8c 100644 --- a/lib/libcxx/include/__charconv/tables.h +++ b/lib/libcxx/include/__charconv/tables.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 namespace __itoa { @@ -62,32 +62,41 @@ inline constexpr char __base_16_lut[512] = { 'f', 'd', 'f', 'e', 'f', 'f'}; inline constexpr uint32_t __pow10_32[10] = { - UINT32_C(0), UINT32_C(10), UINT32_C(100), UINT32_C(1000), UINT32_C(10000), - UINT32_C(100000), UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000), UINT32_C(1000000000)}; + UINT32_C(0), + UINT32_C(10), + UINT32_C(100), + UINT32_C(1000), + UINT32_C(10000), + UINT32_C(100000), + UINT32_C(1000000), + UINT32_C(10000000), + UINT32_C(100000000), + UINT32_C(1000000000)}; -inline constexpr uint64_t __pow10_64[20] = {UINT64_C(0), - UINT64_C(10), - UINT64_C(100), - UINT64_C(1000), - UINT64_C(10000), - UINT64_C(100000), - UINT64_C(1000000), - UINT64_C(10000000), - UINT64_C(100000000), - UINT64_C(1000000000), - UINT64_C(10000000000), - UINT64_C(100000000000), - UINT64_C(1000000000000), - UINT64_C(10000000000000), - UINT64_C(100000000000000), - UINT64_C(1000000000000000), - UINT64_C(10000000000000000), - UINT64_C(100000000000000000), - UINT64_C(1000000000000000000), - UINT64_C(10000000000000000000)}; +inline constexpr uint64_t __pow10_64[20] = { + UINT64_C(0), + UINT64_C(10), + UINT64_C(100), + UINT64_C(1000), + UINT64_C(10000), + UINT64_C(100000), + UINT64_C(1000000), + UINT64_C(10000000), + UINT64_C(100000000), + UINT64_C(1000000000), + UINT64_C(10000000000), + UINT64_C(100000000000), + UINT64_C(1000000000000), + UINT64_C(10000000000000), + UINT64_C(100000000000000), + UINT64_C(1000000000000000), + UINT64_C(10000000000000000), + UINT64_C(100000000000000000), + UINT64_C(1000000000000000000), + UINT64_C(10000000000000000000)}; # ifndef _LIBCPP_HAS_NO_INT128 -inline constexpr int __pow10_128_offset = 0; +inline constexpr int __pow10_128_offset = 0; inline constexpr __uint128_t __pow10_128[40] = { UINT64_C(0), UINT64_C(10), @@ -147,7 +156,7 @@ inline constexpr char __digits_base_10[200] = { } // namespace __itoa -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__charconv/to_chars.h b/lib/libcxx/include/__charconv/to_chars.h new file mode 100644 index 0000000000..8ef09af737 --- /dev/null +++ b/lib/libcxx/include/__charconv/to_chars.h @@ -0,0 +1,25 @@ +// -*- 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___CHARCONV_TO_CHARS +#define _LIBCPP___CHARCONV_TO_CHARS + +#include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_integral.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS diff --git a/lib/libcxx/include/__charconv/to_chars_base_10.h b/lib/libcxx/include/__charconv/to_chars_base_10.h index fc7fb76e3e..33c512e20f 100644 --- a/lib/libcxx/include/__charconv/to_chars_base_10.h +++ b/lib/libcxx/include/__charconv/to_chars_base_10.h @@ -25,7 +25,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 namespace __itoa { @@ -72,7 +72,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __fir static_cast(__value % 100000000)); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u32(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u32(char* __first, uint32_t __value) noexcept { if (__value < 1000000) { if (__value < 10000) { if (__value < 100) { @@ -107,7 +108,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u32(c return __itoa::__append10(__first, __value); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u64(char* __buffer, uint64_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u64(char* __buffer, uint64_t __value) noexcept { if (__value <= UINT32_MAX) return __itoa::__base_10_u32(__buffer, static_cast(__value)); @@ -130,12 +132,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u64(c /// 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_ASSERT(__exp >= __pow10_128_offset, "Index out of bounds"); + _LIBCPP_ASSERT_UNCATEGORIZED(__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 { - _LIBCPP_ASSERT( +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u128(char* __buffer, __uint128_t __value) noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED( __value > numeric_limits::max(), "The optimizations for this algorithm fail when this isn't true."); // Unlike the 64 to 32 bit case the 128 bit case the "upper half" can't be @@ -159,8 +162,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128( __value %= __itoa::__pow_10(29); __buffer = __itoa::__append10(__buffer, static_cast(__value / __itoa::__pow_10(19))); __value %= __itoa::__pow_10(19); - } - else { + } else { // step 2 // This version needs to determine the position of the leading non-zero digit. __buffer = __base_10_u64(__buffer, static_cast(__value / __itoa::__pow_10(19))); @@ -176,7 +178,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128( # endif } // namespace __itoa -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__charconv/to_chars_floating_point.h b/lib/libcxx/include/__charconv/to_chars_floating_point.h new file mode 100644 index 0000000000..08720e1078 --- /dev/null +++ b/lib/libcxx/include/__charconv/to_chars_floating_point.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___CHARCONV_TO_CHARS_FLOATING_POINT_H +#define _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H + +#include <__availability> +#include <__charconv/chars_format.h> +#include <__charconv/to_chars_result.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision); +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H diff --git a/lib/libcxx/include/__charconv/to_chars_integral.h b/lib/libcxx/include/__charconv/to_chars_integral.h new file mode 100644 index 0000000000..28fac7524c --- /dev/null +++ b/lib/libcxx/include/__charconv/to_chars_integral.h @@ -0,0 +1,326 @@ +// -*- 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___CHARCONV_TO_CHARS_INTEGRAL_H +#define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H + +#include <__algorithm/copy_n.h> +#include <__bit/countl.h> +#include <__charconv/tables.h> +#include <__charconv/to_chars_base_10.h> +#include <__charconv/to_chars_result.h> +#include <__charconv/traits.h> +#include <__config> +#include <__system_error/errc.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/make_32_64_or_128_bit.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/unreachable.h> +#include +#include +#include + +#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 + +to_chars_result to_chars(char*, char*, bool, int = 10) = delete; + +template +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 +__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { + auto __x = std::__to_unsigned_like(__value); + if (__value < 0 && __first != __last) { + *__first++ = '-'; + __x = std::__complement(__x); + } + + return std::__to_chars_itoa(__first, __last, __x, false_type()); +} + +template +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; + + if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) + return {__tx::__convert(__first, __value), errc(0)}; + else + return {__last, errc::value_too_large}; +} + +# ifndef _LIBCPP_HAS_NO_INT128 +template <> +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. + // + // NOTE the 128-bit code path requires this optimization. + if (__value <= numeric_limits::max()) + return __to_chars_itoa(__first, __last, static_cast(__value), false_type()); + + using __tx = __itoa::__traits<__uint128_t>; + auto __diff = __last - __first; + + if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) + return {__tx::__convert(__first, __value), errc(0)}; + else + return {__last, errc::value_too_large}; +} +# 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 +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) { + 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()); +} + +namespace __itoa { + +template +struct _LIBCPP_HIDDEN __integral; + +template <> +struct _LIBCPP_HIDDEN __integral<2> { + template + _LIBCPP_HIDE_FROM_ABI static 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); + } + + template + _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); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + const unsigned __divisor = 16; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 4; + std::copy_n(&__base_2_lut[4 * __c], 4, __p); + } + do { + unsigned __c = __value % 2; + __value /= 2; + *--__p = "01"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +template <> +struct _LIBCPP_HIDDEN __integral<8> { + template + _LIBCPP_HIDE_FROM_ABI static 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; + } + + template + _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); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + unsigned __divisor = 64; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 2; + std::copy_n(&__base_8_lut[2 * __c], 2, __p); + } + do { + unsigned __c = __value % 8; + __value /= 8; + *--__p = "01234567"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +template <> +struct _LIBCPP_HIDDEN __integral<16> { + template + _LIBCPP_HIDE_FROM_ABI static 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; + } + + template + _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); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + unsigned __divisor = 256; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 2; + std::copy_n(&__base_16_lut[2 * __c], 2, __p); + } + if (__first != __last) + do { + unsigned __c = __value % 16; + __value /= 16; + *--__p = "0123456789abcdef"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +} // namespace __itoa + +template = sizeof(unsigned)), int>::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { + return __itoa::__integral<_Base>::__width(__value); +} + +template ::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { + return std::__to_chars_integral_width<_Base>(static_cast(__value)); +} + +template = sizeof(unsigned)), int>::type = 0> +_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 ::type = 0> +_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)); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) { + _LIBCPP_ASSERT_UNCATEGORIZED(__value >= 0, "The function requires a non-negative value."); + + unsigned __base_2 = __base * __base; + unsigned __base_3 = __base_2 * __base; + unsigned __base_4 = __base_2 * __base_2; + + int __r = 0; + while (true) { + if (__value < __base) + return __r + 1; + if (__value < __base_2) + return __r + 2; + if (__value < __base_3) + return __r + 3; + if (__value < __base_4) + return __r + 4; + + __value /= __base_4; + __r += 4; + } + + __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) { + if (__base == 10) [[likely]] + return std::__to_chars_itoa(__first, __last, __value, false_type()); + + switch (__base) { + case 2: + return std::__to_chars_integral<2>(__first, __last, __value); + case 8: + return std::__to_chars_integral<8>(__first, __last, __value); + case 16: + return std::__to_chars_integral<16>(__first, __last, __value); + } + + ptrdiff_t __cap = __last - __first; + int __n = std::__to_chars_integral_width(__value, __base); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + do { + unsigned __c = __value % __base; + __value /= __base; + *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; + } while (__value != 0); + return {__last, errc(0)}; +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, _Tp __value) { + using _Type = __make_32_64_or_128_bit_t<_Tp>; + static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars"); + return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>()); +} + +template ::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +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>()); +} + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H diff --git a/lib/libcxx/include/__charconv/to_chars_result.h b/lib/libcxx/include/__charconv/to_chars_result.h index 2eb4098dfc..aba5e5f06b 100644 --- a/lib/libcxx/include/__charconv/to_chars_result.h +++ b/lib/libcxx/include/__charconv/to_chars_result.h @@ -11,7 +11,7 @@ #define _LIBCPP___CHARCONV_TO_CHARS_RESULT_H #include <__config> -#include <__errc> +#include <__system_error/errc.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,18 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -struct _LIBCPP_TYPE_VIS to_chars_result -{ - char* ptr; - errc ec; -# if _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const to_chars_result&, const to_chars_result&) = default; +struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result { + char* ptr; + errc ec; +# if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const to_chars_result&, const to_chars_result&) = default; # endif }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__charconv/traits.h b/lib/libcxx/include/__charconv/traits.h new file mode 100644 index 0000000000..d3884b560d --- /dev/null +++ b/lib/libcxx/include/__charconv/traits.h @@ -0,0 +1,199 @@ +// -*- 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___CHARCONV_TRAITS +#define _LIBCPP___CHARCONV_TRAITS + +#include <__bit/countl.h> +#include <__charconv/tables.h> +#include <__charconv/to_chars_base_10.h> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_unsigned.h> +#include +#include + +#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 + +namespace __itoa { + +template +struct _LIBCPP_HIDDEN __traits_base; + +template +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. + 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; + return __t - (__v < __itoa::__pow10_32[__t]) + 1; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u32(__p, __v); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_32)& __pow() { + return __itoa::__pow10_32; + } +}; + +template +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. + 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; + return __t - (__v < __itoa::__pow10_64[__t]) + 1; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u64(__p, __v); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_64)& __pow() { + return __itoa::__pow10_64; + } +}; + +# ifndef _LIBCPP_HAS_NO_INT128 +template +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t > { + using type = __uint128_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. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __v > 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; + _LIBCPP_ASSERT_UNCATEGORIZED(__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; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u128(__p, __v); + } + + // TODO FMT This pow function should get an index. + // By moving this to its own header it can be reused by the pow function in to_chars_base_10. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_128)& __pow() { + return __itoa::__pow10_128; + } +}; +# endif + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool +__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) { + auto __c = __a * __b; + __r = __c; + return __c > numeric_limits::max(); +} + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool +__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { + auto __c = __a * __b; + __r = __c; + return __c > numeric_limits::max(); +} + +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); +} + +template +inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) { + return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); +} + +template +struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> { + static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; + using __traits_base<_Tp>::__pow; + using typename __traits_base<_Tp>::type; + + // precondition: at least one non-zero character available + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char const* + __read(char const* __p, char const* __ep, type& __a, type& __b) { + type __cprod[digits]; + int __j = digits - 1; + int __i = digits; + do { + if (*__p < '0' || *__p > '9') + break; + __cprod[--__i] = *__p++ - '0'; + } while (__p != __ep && __i != 0); + + __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, __cprod[__i]); + if (__itoa::__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) + --__p; + return __p; + } + + template + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Up + __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) { + for (; __first1 < __last1; ++__first1, ++__first2) + __init = __init + *__first1 * *__first2; + return __init; + } +}; + +} // namespace __itoa + +template +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp __x) { + static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); + return _Tp(~__x + 1); +} + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_TRAITS diff --git a/lib/libcxx/include/__chrono/calendar.h b/lib/libcxx/include/__chrono/calendar.h index d3762a631c..91aaf63253 100644 --- a/lib/libcxx/include/__chrono/calendar.h +++ b/lib/libcxx/include/__chrono/calendar.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -26,12 +26,12 @@ namespace chrono { struct local_t {}; -template -using local_time = time_point; +template +using local_time = time_point; using local_seconds = local_time; using local_days = local_time; -struct last_spec { _LIBCPP_HIDE_FROM_ABI explicit last_spec() = default; }; +struct last_spec { explicit last_spec() = default; }; inline constexpr last_spec last{}; @@ -39,6 +39,6 @@ inline constexpr last_spec last{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_CALENDAR_H diff --git a/lib/libcxx/include/__chrono/concepts.h b/lib/libcxx/include/__chrono/concepts.h new file mode 100644 index 0000000000..61ec256b23 --- /dev/null +++ b/lib/libcxx/include/__chrono/concepts.h @@ -0,0 +1,36 @@ +// -*- 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_CONCEPTS_H +#define _LIBCPP___CHRONO_CONCEPTS_H + +#include <__chrono/hh_mm_ss.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__type_traits/is_specialization.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template +concept __is_hh_mm_ss = __is_specialization_v<_Tp, chrono::hh_mm_ss>; + +template +concept __is_time_point = __is_specialization_v<_Tp, chrono::time_point>; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_CONCEPTS_H diff --git a/lib/libcxx/include/__chrono/convert_to_tm.h b/lib/libcxx/include/__chrono/convert_to_tm.h index 36846b3f71..1301cd6f1f 100644 --- a/lib/libcxx/include/__chrono/convert_to_tm.h +++ b/lib/libcxx/include/__chrono/convert_to_tm.h @@ -10,8 +10,11 @@ #ifndef _LIBCPP___CHRONO_CONVERT_TO_TM_H #define _LIBCPP___CHRONO_CONVERT_TO_TM_H +#include <__chrono/calendar.h> +#include <__chrono/concepts.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> @@ -26,17 +29,23 @@ #include <__chrono/year_month_weekday.h> #include <__concepts/same_as.h> #include <__config> +#include <__format/format_error.h> #include <__memory/addressof.h> +#include <__type_traits/is_convertible.h> #include #include +#include #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 +#if _LIBCPP_STD_VER >= 20 // Conerts a chrono date and weekday to a given _Tm type. // @@ -67,6 +76,24 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday _ return __result; } +template +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const chrono::sys_time<_Duration> __tp) { + chrono::sys_days __days = chrono::floor(__tp); + chrono::year_month_day __ymd{__days}; + + _Tm __result = std::__convert_to_tm<_Tm>(chrono::year_month_day{__ymd}, chrono::weekday{__days}); + + uint64_t __sec = + chrono::duration_cast(__tp - chrono::time_point_cast(__days)).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + + return __result; +} + // Convert a chrono (calendar) time point, or dururation to the given _Tm type, // which must have the same properties as std::tm. template @@ -76,17 +103,37 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { __result.tm_zone = "UTC"; # endif - if constexpr (chrono::__is_duration<_ChronoT>::value) { + if constexpr (__is_time_point<_ChronoT>) { + if constexpr (same_as) + return std::__convert_to_tm<_Tm>(__value); + else 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 + static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization"); + } else if constexpr (chrono::__is_duration<_ChronoT>::value) { // [time.format]/6 // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, // etc.), then a specialization of duration is interpreted as the time of // day elapsed since midnight. - uint64_t __sec = chrono::duration_cast(__value).count(); - __sec %= 24 * 3600; - __result.tm_hour = __sec / 3600; - __sec %= 3600; - __result.tm_min = __sec / 60; - __result.tm_sec = __sec % 60; + + // Not all values can be converted to hours, it may run into ratio + // conversion errors. In that case the conversion to seconds works. + if constexpr (is_convertible_v<_ChronoT, chrono::hours>) { + auto __hour = chrono::floor(__value); + auto __sec = chrono::duration_cast(__value - __hour); + __result.tm_hour = __hour.count() % 24; + __result.tm_min = __sec.count() / 60; + __result.tm_sec = __sec.count() % 60; + } else { + uint64_t __sec = chrono::duration_cast(__value).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + } } else if constexpr (same_as<_ChronoT, chrono::day>) __result.tm_mday = static_cast(__value); else if constexpr (same_as<_ChronoT, chrono::month>) @@ -114,14 +161,26 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || same_as<_ChronoT, chrono::year_month_weekday_last>) { return std::__convert_to_tm<_Tm>(chrono::year_month_day{static_cast(__value)}, __value.weekday()); + } else if constexpr (__is_hh_mm_ss<_ChronoT>) { + __result.tm_sec = __value.seconds().count(); + __result.tm_min = __value.minutes().count(); + // In libc++ hours is stored as a long. The type in std::tm is an int. So + // the overflow can only occur when hour uses more bits than an int + // provides. + if constexpr (sizeof(std::chrono::hours::rep) > sizeof(__result.tm_hour)) + if (__value.hours().count() > std::numeric_limits::max()) + std::__throw_format_error("Formatting hh_mm_ss, encountered an hour overflow"); + __result.tm_hour = __value.hours().count(); } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); return __result; } -#endif //if _LIBCPP_STD_VER > 17 +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___CHRONO_CONVERT_TO_TM_H diff --git a/lib/libcxx/include/__chrono/day.h b/lib/libcxx/include/__chrono/day.h index 35ecfcf9e5..c907c036c1 100644 --- a/lib/libcxx/include/__chrono/day.h +++ b/lib/libcxx/include/__chrono/day.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -29,7 +29,7 @@ class day { private: unsigned char __d_; public: - _LIBCPP_HIDE_FROM_ABI day() = default; + day() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr day(unsigned __val) noexcept : __d_(static_cast(__val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator++() noexcept { ++__d_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } @@ -79,6 +79,6 @@ day& day::operator-=(const days& __dd) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_DAY_H diff --git a/lib/libcxx/include/__chrono/duration.h b/lib/libcxx/include/__chrono/duration.h index afcc38b5cf..96e9671eb5 100644 --- a/lib/libcxx/include/__chrono/duration.h +++ b/lib/libcxx/include/__chrono/duration.h @@ -10,6 +10,8 @@ #ifndef _LIBCPP___CHRONO_DURATION_H #define _LIBCPP___CHRONO_DURATION_H +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include <__config> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> @@ -130,7 +132,7 @@ duration_cast(const duration<_Rep, _Period>& __fd) template struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value; #endif @@ -144,7 +146,7 @@ public: _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {return numeric_limits<_Rep>::lowest();} }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if @@ -186,11 +188,11 @@ round(const duration<_Rep, _Period>& __d) { _ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __upper = __lower + _ToDuration{1}; - auto __lowerDiff = __d - __lower; - auto __upperDiff = __upper - __d; - if (__lowerDiff < __upperDiff) + auto __lower_diff = __d - __lower; + auto __upper_diff = __upper - __d; + if (__lower_diff < __upper_diff) return __lower; - if (__lowerDiff > __upperDiff) + if (__lower_diff > __upper_diff) return __upper; return __lower.count() & 1 ? __upper : __lower; } @@ -242,11 +244,10 @@ private: rep __rep_; public: - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR #ifndef _LIBCPP_CXX03_LANG - duration() = default; + constexpr duration() = default; #else - duration() {} + _LIBCPP_HIDE_FROM_ABI duration() {} #endif template @@ -307,7 +308,7 @@ typedef duration milliseconds; typedef duration seconds; typedef duration< long, ratio< 60> > minutes; typedef duration< long, ratio<3600> > hours; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef duration< int, ratio_multiply, hours::period>> days; typedef duration< int, ratio_multiply, days::period>> weeks; typedef duration< int, ratio_multiply, days::period>> years; @@ -343,6 +344,8 @@ operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return __duration_eq, duration<_Rep2, _Period2> >()(__lhs, __rhs); } +#if _LIBCPP_STD_VER <= 17 + // Duration != template @@ -354,6 +357,8 @@ operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // Duration < template @@ -417,6 +422,20 @@ operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs < __rhs); } +#if _LIBCPP_STD_VER >= 20 + +template + requires three_way_comparable> +_LIBCPP_HIDE_FROM_ABI +constexpr auto operator<=>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) +{ + using _Ct = common_type_t, duration<_Rep2, _Period2>>; + return _Ct(__lhs).count() <=> _Ct(__rhs).count(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // Duration + template @@ -530,7 +549,7 @@ operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2 } // namespace chrono -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // Suffixes for duration literals [time.duration.literals] inline namespace literals { @@ -609,7 +628,7 @@ namespace chrono { // hoist the literals into namespace std::chrono using namespace literals::chrono_literals; } // namespace chrono -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__chrono/file_clock.h b/lib/libcxx/include/__chrono/file_clock.h index ef62b83295..557a880ed4 100644 --- a/lib/libcxx/include/__chrono/file_clock.h +++ b/lib/libcxx/include/__chrono/file_clock.h @@ -27,7 +27,7 @@ struct _FilesystemClock; _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // !_LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,7 +44,7 @@ using file_time = time_point; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM @@ -63,9 +63,9 @@ struct _FilesystemClock { _LIBCPP_EXPORTED_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_FUNC_VIS static time_point now() noexcept; + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_EXPORTED_FROM_ABI static time_point now() noexcept; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI static chrono::sys_time<_Duration> to_sys(const chrono::file_time<_Duration>& __t) { @@ -77,7 +77,7 @@ struct _FilesystemClock { static chrono::file_time<_Duration> from_sys(const chrono::sys_time<_Duration>& __t) { return chrono::file_time<_Duration>(__t.time_since_epoch()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // !_LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__chrono/formatter.h b/lib/libcxx/include/__chrono/formatter.h index 2015783acb..30ed360d4e 100644 --- a/lib/libcxx/include/__chrono/formatter.h +++ b/lib/libcxx/include/__chrono/formatter.h @@ -11,9 +11,11 @@ #define _LIBCPP___CHRONO_FORMATTER_H #include <__chrono/calendar.h> +#include <__chrono/concepts.h> #include <__chrono/convert_to_tm.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> @@ -21,6 +23,7 @@ #include <__chrono/ostream.h> #include <__chrono/parser_std_format_spec.h> #include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> #include <__chrono/year.h> @@ -35,13 +38,12 @@ #include <__format/format_functions.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> -#include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__format/write_escaped.h> #include <__memory/addressof.h> #include #include #include -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -50,7 +52,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -75,13 +77,15 @@ namespace __formatter { // For tiny ratios it's not possible to convert a duration to a hh_mm_ss. This // fails compile-time due to the limited precision of the ratio (64-bit is too // small). Therefore a duration uses its own conversion. -template - requires(chrono::__is_duration<_Tp>::value) -_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { +template +_LIBCPP_HIDE_FROM_ABI void +__format_sub_seconds(const chrono::duration<_Rep, _Period>& __value, basic_stringstream<_CharT>& __sstr) { __sstr << std::use_facet>(__sstr.getloc()).decimal_point(); + using __duration = chrono::duration<_Rep, _Period>; + auto __fraction = __value - chrono::duration_cast(__value); - if constexpr (chrono::treat_as_floating_point_v) + if constexpr (chrono::treat_as_floating_point_v<_Rep>) // When the floating-point value has digits itself they are ignored based // on the wording in [tab:time.format.spec] // If the precision of the input cannot be exactly represented with @@ -96,19 +100,44 @@ _LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_string // https://godbolt.org/z/6dsbnW8ba std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), - __fraction.count(), - chrono::hh_mm_ss<_Tp>::fractional_width); + chrono::duration_cast::precision>(__fraction).count(), + chrono::hh_mm_ss<__duration>::fractional_width); else std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), - __fraction.count(), - chrono::hh_mm_ss<_Tp>::fractional_width); + chrono::duration_cast::precision>(__fraction).count(), + chrono::hh_mm_ss<__duration>::fractional_width); +} + +template +_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { + __formatter::__format_sub_seconds(__value.time_since_epoch(), __sstr); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__format_sub_seconds(const chrono::hh_mm_ss<_Duration>& __value, basic_stringstream<_CharT>& __sstr) { + __sstr << std::use_facet>(__sstr.getloc()).decimal_point(); + if constexpr (chrono::treat_as_floating_point_v) + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), + __value.subseconds().count(), + __value.fractional_width); + else + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), + __value.subseconds().count(), + __value.fractional_width); } template consteval bool __use_fraction() { - if constexpr (chrono::__is_duration<_Tp>::value) + if constexpr (__is_time_point<_Tp>) + return chrono::hh_mm_ss::fractional_width; + else if constexpr (chrono::__is_duration<_Tp>::value) return chrono::hh_mm_ss<_Tp>::fractional_width; + else if constexpr (__is_hh_mm_ss<_Tp>) + return _Tp::fractional_width; else return false; } @@ -169,7 +198,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( if (__year < 1000 || __year > 9999) __formatter::__format_century(__year, __sstr); else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); } break; case _CharT('j'): @@ -180,7 +209,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // an intemediate step. __sstr << chrono::duration_cast(chrono::duration_cast(__value)).count(); else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); break; case _CharT('q'): @@ -208,7 +237,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( case _CharT('S'): case _CharT('T'): - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); if constexpr (__use_fraction<_Tp>()) __formatter::__format_sub_seconds(__value, __sstr); break; @@ -240,20 +269,19 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // // TODO FMT evaluate the comment above. -# if defined(__GLIBC__) || defined(_AIX) +# if defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) case _CharT('y'): // Glibc fails for negative values, AIX for positive values too. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100); break; -# endif // defined(__GLIBC__) || defined(_AIX) +# endif // defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) - case _CharT('Y'): { - int __year = __t.tm_year + 1900; - if (__year < 1000) - __formatter::__format_year(__year, __sstr); - else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); - } break; + case _CharT('Y'): + // Depending on the platform's libc the range of supported years is + // limited. Intead of of testing all conditions use the internal + // implementation unconditionally. + __formatter::__format_year(__t.tm_year + 1900, __sstr); + break; case _CharT('F'): { int __year = __t.tm_year + 1900; @@ -261,9 +289,14 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( __formatter::__format_year(__year, __sstr); __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); } else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); } break; + case _CharT('Z'): + // TODO FMT Add proper timezone support. + __sstr << _LIBCPP_STATICALLY_WIDEN(_CharT, "UTC"); + break; + case _CharT('O'): if constexpr (__use_fraction<_Tp>()) { // Handle OS using the normal representation for the non-fractional @@ -271,7 +304,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // fractional part should be formatted. if (*(__it + 1) == 'S') { ++__it; - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); __formatter::__format_sub_seconds(__value, __sstr); break; } @@ -281,7 +314,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( ++__it; [[fallthrough]]; default: - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); break; } } else { @@ -292,7 +325,9 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( template _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -322,13 +357,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.weekday().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -358,13 +397,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.weekday().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -394,13 +437,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { return __value.ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -430,16 +477,18 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return __value.month().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.month().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } -template +template _LIBCPP_HIDE_FROM_ABI auto __format_chrono(const _Tp& __value, - auto& __ctx, + _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, - basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) { + basic_string_view<_CharT> __chrono_specs) { basic_stringstream<_CharT> __sstr; // [time.format]/2 // 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise @@ -464,42 +513,63 @@ __format_chrono(const _Tp& __value, } else { // Test __weekday_name_ before __weekday_ to give a better error. if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value)) - std::__throw_format_error("formatting a weekday name needs a valid weekday"); + std::__throw_format_error("Formatting a weekday name needs a valid weekday"); if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value)) - std::__throw_format_error("formatting a weekday needs a valid weekday"); + std::__throw_format_error("Formatting a weekday needs a valid weekday"); if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value)) - std::__throw_format_error("formatting a day of year needs a valid date"); + std::__throw_format_error("Formatting a day of year needs a valid date"); if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value)) - std::__throw_format_error("formatting a week of year needs a valid date"); + std::__throw_format_error("Formatting a week of year needs a valid date"); if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value)) - std::__throw_format_error("formatting a month name from an invalid month number"); + std::__throw_format_error("Formatting a month name from an invalid month number"); + + if constexpr (__is_hh_mm_ss<_Tp>) { + // Note this is a pedantic intepretation of the Standard. A hh_mm_ss + // is no longer a time_of_day and can store an arbitrary number of + // hours. A number of hours in a 12 or 24 hour clock can't represent + // 24 hours or more. The functions std::chrono::make12 and + // std::chrono::make24 reaffirm this view point. + // + // Interestingly this will be the only output stream function that + // throws. + // + // TODO FMT The wording probably needs to be adapted to + // - The displayed hours is hh_mm_ss.hours() % 24 + // - It should probably allow %j in the same fashion as duration. + // - The stream formatter should change its output when hours >= 24 + // - Write it as not valid, + // - or write the number of days. + if (__specs.__chrono_.__hour_ && __value.hours().count() > 23) + std::__throw_format_error("Formatting a hour needs a valid value"); + + if (__value.is_negative()) + __sstr << _CharT('-'); + } __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs); } } - // TODO FMT Use the stringstream's view after P0408R7 has been implemented. - basic_string<_CharT> __str = __sstr.str(); - return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + return __formatter::__write_string(__sstr.view(), __ctx.out(), __specs); } } // namespace __formatter template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono { +struct _LIBCPP_TEMPLATE_VIS __formatter_chrono { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto __parse( - basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) - -> decltype(__parse_ctx.begin()) { - return __parser_.__parse(__parse_ctx, __fields, __flags); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse(_ParseContext& __ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) { + return __parser_.__parse(__ctx, __fields, __flags); } - template - _LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __value, _FormatContext& __ctx) const { return __formatter::__format_chrono( __value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_); } @@ -507,13 +577,47 @@ public: __format_spec::__parser_chrono<_CharT> __parser_; }; +template +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __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 _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __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 _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + // The flags are not __clock since there is no associated time-zone. + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date_time); + } +}; + template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { // [time.format]/1 // Giving a precision specification in the chrono-format-spec is valid only // for std::chrono::duration types where the representation type Rep is a @@ -523,193 +627,203 @@ public: // // Note this doesn't refer to chrono::treat_as_floating_point_v<_Rep>. if constexpr (std::floating_point<_Rep>) - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); + return _Base::__parse(__ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); else - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; -#endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +template +struct formatter, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __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::__time); + } +}; +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__chrono/hh_mm_ss.h b/lib/libcxx/include/__chrono/hh_mm_ss.h index fd61cbe8f8..5bd452e57f 100644 --- a/lib/libcxx/include/__chrono/hh_mm_ss.h +++ b/lib/libcxx/include/__chrono/hh_mm_ss.h @@ -13,14 +13,14 @@ #include <__chrono/duration.h> #include <__chrono/time_point.h> #include <__config> +#include <__type_traits/common_type.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -85,6 +85,7 @@ private: chrono::seconds __s_; precision __f_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(hh_mm_ss); _LIBCPP_HIDE_FROM_ABI constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } _LIBCPP_HIDE_FROM_ABI constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); } @@ -107,6 +108,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr hours make24(const hours& __h, bool __is_pm) noe _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_HH_MM_SS_H diff --git a/lib/libcxx/include/__chrono/literals.h b/lib/libcxx/include/__chrono/literals.h index 50529bd44a..28ddc43a2c 100644 --- a/lib/libcxx/include/__chrono/literals.h +++ b/lib/libcxx/include/__chrono/literals.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,6 +44,6 @@ namespace chrono { // hoist the literals into namespace std::chrono _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_LITERALS_H diff --git a/lib/libcxx/include/__chrono/month.h b/lib/libcxx/include/__chrono/month.h index e929f24884..7566e4ed29 100644 --- a/lib/libcxx/include/__chrono/month.h +++ b/lib/libcxx/include/__chrono/month.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -29,11 +29,11 @@ class month { private: unsigned char __m_; public: - _LIBCPP_HIDE_FROM_ABI month() = default; + month() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr month(unsigned __val) noexcept : __m_(static_cast(__val)) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { ++__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { *this += months{1}; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { --__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { *this -= months{1}; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr month& operator+=(const months& __m1) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr month& operator-=(const months& __m1) noexcept; @@ -98,6 +98,6 @@ inline constexpr month December{12}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTH_H diff --git a/lib/libcxx/include/__chrono/month_weekday.h b/lib/libcxx/include/__chrono/month_weekday.h index 01cdf76d84..eb9e42d01f 100644 --- a/lib/libcxx/include/__chrono/month_weekday.h +++ b/lib/libcxx/include/__chrono/month_weekday.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,10 +41,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept { return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - _LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept { return month_weekday{__lhs, __rhs}; } @@ -77,11 +73,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept { return __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - - _LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept { return month_weekday_last{__lhs, __rhs}; } @@ -101,6 +92,6 @@ month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTH_WEEKDAY_H diff --git a/lib/libcxx/include/__chrono/monthday.h b/lib/libcxx/include/__chrono/monthday.h index c0ee3e4a94..03fd7503a6 100644 --- a/lib/libcxx/include/__chrono/monthday.h +++ b/lib/libcxx/include/__chrono/monthday.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,7 +32,7 @@ private: chrono::month __m_; chrono::day __d_; public: - _LIBCPP_HIDE_FROM_ABI month_day() = default; + month_day() = default; _LIBCPP_HIDE_FROM_ABI constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept : __m_{__mval}, __d_{__dval} {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } @@ -124,6 +124,6 @@ month_day_last operator/(last_spec, int __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTHDAY_H diff --git a/lib/libcxx/include/__chrono/ostream.h b/lib/libcxx/include/__chrono/ostream.h index 30a04bd265..f171944b5c 100644 --- a/lib/libcxx/include/__chrono/ostream.h +++ b/lib/libcxx/include/__chrono/ostream.h @@ -10,12 +10,16 @@ #ifndef _LIBCPP___CHRONO_OSTREAM_H #define _LIBCPP___CHRONO_OSTREAM_H +#include <__chrono/calendar.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> +#include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> #include <__chrono/weekday.h> #include <__chrono/year.h> #include <__chrono/year_month.h> @@ -33,10 +37,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace chrono { +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_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 file_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 local_time<_Duration> __tp) { + return __os << sys_time<_Duration>{__tp.time_since_epoch()}; +} + // Depending on the type the return is a const _CharT* or a basic_string<_CharT> template _LIBCPP_HIDE_FROM_ABI auto __units_suffix() { @@ -92,7 +114,7 @@ _LIBCPP_HIDE_FROM_ABI auto __units_suffix() { } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) { basic_ostringstream<_CharT, _Traits> __s; __s.flags(__os.flags()); @@ -103,21 +125,19 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { - return __os - << (__d.ok() - ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) - // Note this error differs from the wording of the Standard. The - // Standard wording doesn't work well on AIX or Windows. There - // the formatted day seems to be either modulo 100 or completely - // omitted. Judging by the wording this is valid. - // TODO FMT Write a paper of file an LWG issue. - : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast(__d))); +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { + return __os << (__d.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) + // Note this error differs from the wording of the Standard. The + // Standard wording doesn't work well on AIX or Windows. There + // the formatted day seems to be either modulo 100 or completely + // omitted. Judging by the wording this is valid. + // TODO FMT Write a paper of file an LWG issue. + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), + static_cast(__d))); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { return __os << (__m.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%b}"), __m) : std::format(__os.getloc(), @@ -126,14 +146,14 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) { return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y) : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y)); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { return __os << (__wd.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%a}"), __wd) : std::format(__os.getloc(), // TODO FMT Standard mandated locale isn't used. @@ -142,7 +162,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { auto __i = __wdi.index(); return __os << (__i >= 1 && __i <= 5 @@ -154,13 +174,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { // TODO FMT The Standard allows 30th of February to be printed. // It would be nice to show an error message instead. @@ -168,47 +188,47 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday& __mwd) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday_last& __mwdl) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day& __ymd) { return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day_last& __ymdl) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymwd) { return __os << std::format( __os.getloc(), @@ -219,7 +239,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymw } template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { return __os << std::format( __os.getloc(), @@ -229,9 +249,15 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl.weekday_last()); } +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); +} + } // namespace chrono -#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__chrono/parser_std_format_spec.h b/lib/libcxx/include/__chrono/parser_std_format_spec.h index dbcfe6da60..296be8794e 100644 --- a/lib/libcxx/include/__chrono/parser_std_format_spec.h +++ b/lib/libcxx/include/__chrono/parser_std_format_spec.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace __format_spec { @@ -137,17 +137,19 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { template class _LIBCPP_TEMPLATE_VIS __parser_chrono { + using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags) - -> decltype(__parse_ctx.begin()) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields); - const _CharT* __end = __parse_ctx.end(); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse(_ParseContext& __ctx, __fields __fields, __flags __flags) { + _ConstIterator __begin = __parser_.__parse(__ctx, __fields); + _ConstIterator __end = __ctx.end(); if (__begin == __end) return __begin; - const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags); - __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; + _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags); + __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; return __last; } @@ -156,19 +158,20 @@ public: basic_string_view<_CharT> __chrono_specs_; private: - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* - __parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) { - _LIBCPP_ASSERT(__begin != __end, - "When called with an empty input the function will cause " - "undefined behavior by evaluating data not in the input"); + _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator + __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __begin != __end, + "When called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); if (*__begin != _CharT('%') && *__begin != _CharT('}')) - std::__throw_format_error("Expected '%' or '}' in the chrono format-string"); + std::__throw_format_error("The format specifier expects a '%' or a '}'"); do { switch (*__begin) { case _CharT('{'): - std::__throw_format_error("The chrono-specs contains a '{'"); + std::__throw_format_error("The chrono specifiers contain a '{'"); case _CharT('}'): return __begin; @@ -190,10 +193,10 @@ private: /// \pre *__begin == '%' /// \post __begin points at the end parsed conversion-spec _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) - std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec"); + std::__throw_format_error("End of input while parsing a conversion specifier"); switch (*__begin) { case _CharT('n'): @@ -212,6 +215,7 @@ private: case _CharT('p'): // TODO FMT does the formater require an hour or a time? case _CharT('H'): case _CharT('I'): + __parser_.__hour_ = true; __validate_hour(__flags); break; @@ -219,6 +223,7 @@ private: case _CharT('R'): case _CharT('T'): case _CharT('X'): + __parser_.__hour_ = true; __format_spec::__validate_time(__flags); break; @@ -304,13 +309,14 @@ private: /// \pre *__begin == 'E' /// \post __begin is incremented by one. _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) std::__throw_format_error("End of input while parsing the modifier E"); switch (*__begin) { case _CharT('X'): + __parser_.__hour_ = true; __format_spec::__validate_time(__flags); break; @@ -343,7 +349,7 @@ private: /// \pre *__begin == 'O' /// \post __begin is incremented by one. _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) std::__throw_format_error("End of input while parsing the modifier O"); @@ -359,6 +365,7 @@ private: case _CharT('I'): case _CharT('H'): + __parser_.__hour_ = true; __format_spec::__validate_hour(__flags); break; @@ -403,7 +410,7 @@ private: } // namespace __format_spec -#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__chrono/statically_widen.h b/lib/libcxx/include/__chrono/statically_widen.h index 360b6c2c7d..a18c46f057 100644 --- a/lib/libcxx/include/__chrono/statically_widen.h +++ b/lib/libcxx/include/__chrono/statically_widen.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <__fmt_char_type _CharT> @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __s return __wstr; } # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str) -# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS // Without this indirection the unit test test/libcxx/modules_include.sh.cpp // fails for the CI build "No wide characters". This seems like a bug. @@ -45,7 +45,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __s # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str) # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__chrono/steady_clock.h b/lib/libcxx/include/__chrono/steady_clock.h index ba83351738..cdcd2fa0d9 100644 --- a/lib/libcxx/include/__chrono/steady_clock.h +++ b/lib/libcxx/include/__chrono/steady_clock.h @@ -24,7 +24,7 @@ namespace chrono { #ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK -class _LIBCPP_TYPE_VIS steady_clock +class _LIBCPP_EXPORTED_FROM_ABI steady_clock { public: typedef nanoseconds duration; diff --git a/lib/libcxx/include/__chrono/system_clock.h b/lib/libcxx/include/__chrono/system_clock.h index 331db46801..06fe071df2 100644 --- a/lib/libcxx/include/__chrono/system_clock.h +++ b/lib/libcxx/include/__chrono/system_clock.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { -class _LIBCPP_TYPE_VIS system_clock +class _LIBCPP_EXPORTED_FROM_ABI system_clock { public: typedef microseconds duration; @@ -38,7 +38,7 @@ public: static time_point from_time_t(time_t __t) _NOEXCEPT; }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template using sys_time = time_point; diff --git a/lib/libcxx/include/__chrono/time_point.h b/lib/libcxx/include/__chrono/time_point.h index 8a8fa2176d..c14835401f 100644 --- a/lib/libcxx/include/__chrono/time_point.h +++ b/lib/libcxx/include/__chrono/time_point.h @@ -11,6 +11,8 @@ #define _LIBCPP___CHRONO_TIME_POINT_H #include <__chrono/duration.h> +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include <__config> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> @@ -90,7 +92,7 @@ time_point_cast(const time_point<_Clock, _Duration>& __t) return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if @@ -138,7 +140,7 @@ abs(duration<_Rep, _Period> __d) { return __d >= __d.zero() ? +__d : -__d; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 // time_point == @@ -150,6 +152,8 @@ operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return __lhs.time_since_epoch() == __rhs.time_since_epoch(); } +#if _LIBCPP_STD_VER <= 17 + // time_point != template @@ -160,6 +164,8 @@ operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // time_point < template @@ -200,6 +206,16 @@ operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return !(__lhs < __rhs); } +#if _LIBCPP_STD_VER >= 20 + +template _Duration2> +_LIBCPP_HIDE_FROM_ABI constexpr auto +operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { + return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // time_point operator+(time_point x, duration y); template diff --git a/lib/libcxx/include/__chrono/weekday.h b/lib/libcxx/include/__chrono/weekday.h index e0bc8a4cae..776d8ed312 100644 --- a/lib/libcxx/include/__chrono/weekday.h +++ b/lib/libcxx/include/__chrono/weekday.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,7 +35,7 @@ private: unsigned char __wd_; _LIBCPP_HIDE_FROM_ABI static constexpr unsigned char __weekday_from_days(int __days) noexcept; public: - _LIBCPP_HIDE_FROM_ABI weekday() = default; + weekday() = default; _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(unsigned __val) noexcept : __wd_(static_cast(__val == 7 ? 0 : __val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr weekday(const sys_days& __sysd) noexcept : __wd_(__weekday_from_days(__sysd.time_since_epoch().count())) {} @@ -69,10 +69,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept { return __lhs.c_encoding() == __rhs.c_encoding(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept { return __lhs.c_encoding() < __rhs.c_encoding(); } @@ -126,7 +122,7 @@ private: chrono::weekday __wd_; unsigned char __idx_; public: - _LIBCPP_HIDE_FROM_ABI weekday_indexed() = default; + weekday_indexed() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept : __wd_{__wdval}, __idx_(__idxval) {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wd_; } @@ -138,11 +134,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept { return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept -{ return !(__lhs == __rhs); } - - class weekday_last { private: chrono::weekday __wd_; @@ -157,10 +148,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept { return __lhs.weekday() == __rhs.weekday(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - _LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; } @@ -180,6 +167,6 @@ inline constexpr weekday Saturday{6}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_WEEKDAY_H diff --git a/lib/libcxx/include/__chrono/year.h b/lib/libcxx/include/__chrono/year.h index 79ee8a02b8..14bcbdafdd 100644 --- a/lib/libcxx/include/__chrono/year.h +++ b/lib/libcxx/include/__chrono/year.h @@ -22,7 +22,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,7 +33,7 @@ class year { private: short __y_; public: - _LIBCPP_HIDE_FROM_ABI year() = default; + year() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr year(int __val) noexcept : __y_(static_cast(__val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator++() noexcept { ++__y_; return *this; } @@ -95,7 +95,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__chrono/year_month.h b/lib/libcxx/include/__chrono/year_month.h index 9f1e65c8c8..f4eea8427f 100644 --- a/lib/libcxx/include/__chrono/year_month.h +++ b/lib/libcxx/include/__chrono/year_month.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -31,7 +31,7 @@ class year_month { chrono::year __y_; chrono::month __m_; public: - _LIBCPP_HIDE_FROM_ABI year_month() = default; + year_month() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept : __y_{__yval}, __m_{__mval} {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } @@ -96,6 +96,6 @@ year_month operator-(const year_month& __lhs, const years& __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_H diff --git a/lib/libcxx/include/__chrono/year_month_day.h b/lib/libcxx/include/__chrono/year_month_day.h index b74901470c..ed5903f7d3 100644 --- a/lib/libcxx/include/__chrono/year_month_day.h +++ b/lib/libcxx/include/__chrono/year_month_day.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,7 +42,7 @@ private: chrono::month __m_; chrono::day __d_; public: - _LIBCPP_HIDE_FROM_ABI year_month_day() = default; + year_month_day() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day( const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept : __y_{__yval}, __m_{__mval}, __d_{__dval} {} @@ -302,6 +302,6 @@ bool year_month_day::ok() const noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_DAY_H diff --git a/lib/libcxx/include/__chrono/year_month_weekday.h b/lib/libcxx/include/__chrono/year_month_weekday.h index 6604deaf12..4b5cb492a1 100644 --- a/lib/libcxx/include/__chrono/year_month_weekday.h +++ b/lib/libcxx/include/__chrono/year_month_weekday.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,7 +39,7 @@ class year_month_weekday { chrono::month __m_; chrono::weekday_indexed __wdi_; public: - _LIBCPP_HIDE_FROM_ABI year_month_weekday() = default; + year_month_weekday() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept : __y_{__yval}, __m_{__mval}, __wdi_{__wdival} {} @@ -98,10 +98,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept { return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; } @@ -191,11 +187,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last operator/(const year_month& __lhs, const weekday_last& __rhs) noexcept { return year_month_weekday_last{__lhs.year(), __lhs.month(), __rhs}; } @@ -250,6 +241,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekd _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_WEEKDAY_H diff --git a/lib/libcxx/include/__compare/common_comparison_category.h b/lib/libcxx/include/__compare/common_comparison_category.h index 06c4b28491..5fad99bf5c 100644 --- a/lib/libcxx/include/__compare/common_comparison_category.h +++ b/lib/libcxx/include/__compare/common_comparison_category.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __comp_detail { @@ -65,14 +65,14 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() { using _CCC = _ClassifyCompCategory; constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; - constexpr _CCC _Cat = __comp_detail::__compute_comp_type(__type_kinds); - if constexpr (_Cat == _None) + constexpr _CCC __cat = __comp_detail::__compute_comp_type(__type_kinds); + if constexpr (__cat == _None) return void(); - else if constexpr (_Cat == _PartialOrd) + else if constexpr (__cat == _PartialOrd) return partial_ordering::equivalent; - else if constexpr (_Cat == _WeakOrd) + else if constexpr (__cat == _WeakOrd) return weak_ordering::equivalent; - else if constexpr (_Cat == _StrongOrd) + else if constexpr (__cat == _StrongOrd) return strong_ordering::equivalent; else static_assert(_False, "unhandled case"); @@ -88,7 +88,7 @@ struct _LIBCPP_TEMPLATE_VIS common_comparison_category { template using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/compare_partial_order_fallback.h b/lib/libcxx/include/__compare/compare_partial_order_fallback.h index 06f03fe7ad..fb2921ed52 100644 --- a/lib/libcxx/include/__compare/compare_partial_order_fallback.h +++ b/lib/libcxx/include/__compare/compare_partial_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_partial_order_fallback { @@ -67,7 +67,7 @@ inline namespace __cpo { inline constexpr auto compare_partial_order_fallback = __compare_partial_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/compare_strong_order_fallback.h b/lib/libcxx/include/__compare/compare_strong_order_fallback.h index 869386817a..d84d065e40 100644 --- a/lib/libcxx/include/__compare/compare_strong_order_fallback.h +++ b/lib/libcxx/include/__compare/compare_strong_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_strong_order_fallback { @@ -64,7 +64,7 @@ inline namespace __cpo { inline constexpr auto compare_strong_order_fallback = __compare_strong_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/compare_three_way.h b/lib/libcxx/include/__compare/compare_three_way.h index fdbba04a78..2bc63a00e5 100644 --- a/lib/libcxx/include/__compare/compare_three_way.h +++ b/lib/libcxx/include/__compare/compare_three_way.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _LIBCPP_TEMPLATE_VIS compare_three_way { @@ -34,7 +34,7 @@ struct _LIBCPP_TEMPLATE_VIS compare_three_way using is_transparent = void; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/compare_three_way_result.h b/lib/libcxx/include/__compare/compare_three_way_result.h index 8885d7effa..632ebdce1b 100644 --- a/lib/libcxx/include/__compare/compare_three_way_result.h +++ b/lib/libcxx/include/__compare/compare_three_way_result.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; @@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_resul template using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/compare_weak_order_fallback.h b/lib/libcxx/include/__compare/compare_weak_order_fallback.h index f434dcb4a3..d3ba04a86b 100644 --- a/lib/libcxx/include/__compare/compare_weak_order_fallback.h +++ b/lib/libcxx/include/__compare/compare_weak_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_weak_order_fallback { @@ -64,7 +64,7 @@ inline namespace __cpo { inline constexpr auto compare_weak_order_fallback = __compare_weak_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/is_eq.h b/lib/libcxx/include/__compare/is_eq.h index 49648924e8..9a82df1ebe 100644 --- a/lib/libcxx/include/__compare/is_eq.h +++ b/lib/libcxx/include/__compare/is_eq.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; } _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_neq(partial_ordering __c) noexcept { return __c != 0; } @@ -27,7 +27,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexce _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gt(partial_ordering __c) noexcept { return __c > 0; } _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/ordering.h b/lib/libcxx/include/__compare/ordering.h index ff148abf23..c348f0433a 100644 --- a/lib/libcxx/include/__compare/ordering.h +++ b/lib/libcxx/include/__compare/ordering.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // exposition only enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { @@ -40,7 +40,7 @@ template inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); struct _CmpUnspecifiedParam { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL + _LIBCPP_HIDE_FROM_ABI constexpr _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} template>> @@ -319,7 +319,7 @@ inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater) template concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/partial_order.h b/lib/libcxx/include/__compare/partial_order.h index aee07ebb42..9cb76cc5bd 100644 --- a/lib/libcxx/include/__compare/partial_order.h +++ b/lib/libcxx/include/__compare/partial_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __partial_order { @@ -67,7 +67,7 @@ inline namespace __cpo { inline constexpr auto partial_order = __partial_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/strong_order.h b/lib/libcxx/include/__compare/strong_order.h index 05856c2093..b6e0cfaaa5 100644 --- a/lib/libcxx/include/__compare/strong_order.h +++ b/lib/libcxx/include/__compare/strong_order.h @@ -30,7 +30,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __strong_order { @@ -130,7 +130,7 @@ inline namespace __cpo { inline constexpr auto strong_order = __strong_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/synth_three_way.h b/lib/libcxx/include/__compare/synth_three_way.h index 7d338987e0..6420d1362d 100644 --- a/lib/libcxx/include/__compare/synth_three_way.h +++ b/lib/libcxx/include/__compare/synth_three_way.h @@ -21,30 +21,36 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [expos.only.func] -_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = - [](const _Tp& __t, const _Up& __u) - requires requires { - { __t < __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - } - { - if constexpr (three_way_comparable_with<_Tp, _Up>) { - return __t <=> __u; - } else { - if (__t < __u) return weak_ordering::less; - if (__u < __t) return weak_ordering::greater; - return weak_ordering::equivalent; - } - }; +// TODO MODULES restore the lamba to match the Standard. +// See https://github.com/llvm/llvm-project/issues/57222 +//_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = +// [](const _Tp& __t, const _Up& __u) +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up& __u) + requires requires { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } +{ + if constexpr (three_way_comparable_with<_Tp, _Up>) { + return __t <=> __u; + } else { + if (__t < __u) + return weak_ordering::less; + if (__u < __t) + return weak_ordering::greater; + return weak_ordering::equivalent; + } +} template using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/three_way_comparable.h b/lib/libcxx/include/__compare/three_way_comparable.h index 6c98916d85..2b77bc3f54 100644 --- a/lib/libcxx/include/__compare/three_way_comparable.h +++ b/lib/libcxx/include/__compare/three_way_comparable.h @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template concept __compares_as = @@ -52,7 +52,7 @@ concept three_way_comparable_with = { __u <=> __t } -> __compares_as<_Cat>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__compare/weak_order.h b/lib/libcxx/include/__compare/weak_order.h index abb24e3665..9cbc1d24aa 100644 --- a/lib/libcxx/include/__compare/weak_order.h +++ b/lib/libcxx/include/__compare/weak_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __weak_order { @@ -95,7 +95,7 @@ inline namespace __cpo { inline constexpr auto weak_order = __weak_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/arithmetic.h b/lib/libcxx/include/__concepts/arithmetic.h index 215b52aa02..f41e4c9f27 100644 --- a/lib/libcxx/include/__concepts/arithmetic.h +++ b/lib/libcxx/include/__concepts/arithmetic.h @@ -22,20 +22,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.arithmetic], arithmetic concepts -template +template concept integral = is_integral_v<_Tp>; -template +template concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; -template +template concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; -template +template concept floating_point = is_floating_point_v<_Tp>; // Concept helpers for the internal type traits for the fundamental types. @@ -45,7 +45,7 @@ concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; template concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/assignable.h b/lib/libcxx/include/__concepts/assignable.h index 91edd400ad..3f7544c934 100644 --- a/lib/libcxx/include/__concepts/assignable.h +++ b/lib/libcxx/include/__concepts/assignable.h @@ -22,19 +22,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.assignable] -template +template concept assignable_from = - is_lvalue_reference_v<_Lhs> && - common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && - requires (_Lhs __lhs, _Rhs&& __rhs) { - { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; - }; + is_lvalue_reference_v<_Lhs> && + common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && + requires(_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; + }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/boolean_testable.h b/lib/libcxx/include/__concepts/boolean_testable.h index a96bde7117..d290e1cf3d 100644 --- a/lib/libcxx/include/__concepts/boolean_testable.h +++ b/lib/libcxx/include/__concepts/boolean_testable.h @@ -19,19 +19,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.booleantestable] -template +template concept __boolean_testable_impl = convertible_to<_Tp, bool>; -template +template concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { { !_VSTD::forward<_Tp>(__t) } -> __boolean_testable_impl; }; -#endif // _LIBCPP_STD_VER > 17 +#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 c4d2f98952..c1b4a8c258 100644 --- a/lib/libcxx/include/__concepts/class_or_enum.h +++ b/lib/libcxx/include/__concepts/class_or_enum.h @@ -21,19 +21,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Whether a type is a class type or enumeration type according to the Core wording. -template +template concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; // Work around Clang bug https://llvm.org/PR52970 // TODO: remove this workaround once libc++ no longer has to support Clang 13 (it was fixed in Clang 14). -template +template concept __workaround_52970 = is_class_v<__remove_cvref_t<_Tp>> || is_union_v<__remove_cvref_t<_Tp>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/common_reference_with.h b/lib/libcxx/include/__concepts/common_reference_with.h index cc92762d31..4eb687e071 100644 --- a/lib/libcxx/include/__concepts/common_reference_with.h +++ b/lib/libcxx/include/__concepts/common_reference_with.h @@ -20,17 +20,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.commonref] -template +template concept common_reference_with = - same_as, common_reference_t<_Up, _Tp>> && - convertible_to<_Tp, common_reference_t<_Tp, _Up>> && - convertible_to<_Up, common_reference_t<_Tp, _Up>>; + same_as, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && convertible_to<_Up, common_reference_t<_Tp, _Up>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/common_with.h b/lib/libcxx/include/__concepts/common_with.h index 569a0ee3b7..85abb05efb 100644 --- a/lib/libcxx/include/__concepts/common_with.h +++ b/lib/libcxx/include/__concepts/common_with.h @@ -23,27 +23,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.common] -template +// clang-format off +template concept common_with = - same_as, common_type_t<_Up, _Tp>> && - requires { - static_cast>(std::declval<_Tp>()); - static_cast>(std::declval<_Up>()); - } && - common_reference_with< - add_lvalue_reference_t, - add_lvalue_reference_t> && - common_reference_with< - add_lvalue_reference_t>, - common_reference_t< - add_lvalue_reference_t, - add_lvalue_reference_t>>; + same_as, common_type_t<_Up, _Tp>> && + requires { + static_cast>(std::declval<_Tp>()); + static_cast>(std::declval<_Up>()); + } && + common_reference_with< + add_lvalue_reference_t, + add_lvalue_reference_t> && + common_reference_with< + add_lvalue_reference_t>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/constructible.h b/lib/libcxx/include/__concepts/constructible.h index 1d78eb5fd1..835a44429c 100644 --- a/lib/libcxx/include/__concepts/constructible.h +++ b/lib/libcxx/include/__concepts/constructible.h @@ -20,36 +20,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.constructible] -template -concept constructible_from = - destructible<_Tp> && is_constructible_v<_Tp, _Args...>; +template +concept constructible_from = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; // [concept.default.init] -template +template concept __default_initializable = requires { ::new _Tp; }; -template -concept default_initializable = constructible_from<_Tp> && - requires { _Tp{}; } && __default_initializable<_Tp>; +template +concept default_initializable = constructible_from<_Tp> && requires { _Tp{}; } && __default_initializable<_Tp>; // [concept.moveconstructible] -template -concept move_constructible = - constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; +template +concept move_constructible = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; // [concept.copyconstructible] -template +// clang-format off +template concept copy_constructible = - move_constructible<_Tp> && - constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && - constructible_from<_Tp, const _Tp&> && convertible_to && - constructible_from<_Tp, const _Tp> && convertible_to; + move_constructible<_Tp> && + constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && + constructible_from<_Tp, const _Tp&> && convertible_to && + constructible_from<_Tp, const _Tp> && convertible_to; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/convertible_to.h b/lib/libcxx/include/__concepts/convertible_to.h index 2c1d267410..6d5b6c1268 100644 --- a/lib/libcxx/include/__concepts/convertible_to.h +++ b/lib/libcxx/include/__concepts/convertible_to.h @@ -19,18 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.convertible] -template -concept convertible_to = - is_convertible_v<_From, _To> && - requires { - static_cast<_To>(std::declval<_From>()); - }; +template +concept convertible_to = is_convertible_v<_From, _To> && requires { static_cast<_To>(std::declval<_From>()); }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/copyable.h b/lib/libcxx/include/__concepts/copyable.h index c5d8a80b9d..2bf0ad42fc 100644 --- a/lib/libcxx/include/__concepts/copyable.h +++ b/lib/libcxx/include/__concepts/copyable.h @@ -20,19 +20,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.object] -template +// clang-format off +template concept copyable = - copy_constructible<_Tp> && - movable<_Tp> && - assignable_from<_Tp&, _Tp&> && - assignable_from<_Tp&, const _Tp&> && - assignable_from<_Tp&, const _Tp>; + copy_constructible<_Tp> && + movable<_Tp> && + assignable_from<_Tp&, _Tp&> && + assignable_from<_Tp&, const _Tp&> && + assignable_from<_Tp&, const _Tp>; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/derived_from.h b/lib/libcxx/include/__concepts/derived_from.h index 0d3462df6a..9875faee81 100644 --- a/lib/libcxx/include/__concepts/derived_from.h +++ b/lib/libcxx/include/__concepts/derived_from.h @@ -19,16 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.derived] -template -concept derived_from = - is_base_of_v<_Bp, _Dp> && - is_convertible_v; +template +concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/destructible.h b/lib/libcxx/include/__concepts/destructible.h index ad3819d5dc..28b4b1bc24 100644 --- a/lib/libcxx/include/__concepts/destructible.h +++ b/lib/libcxx/include/__concepts/destructible.h @@ -18,14 +18,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.destructible] -template +template concept destructible = is_nothrow_destructible_v<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/different_from.h b/lib/libcxx/include/__concepts/different_from.h index 15fd8f0551..fd31f6e258 100644 --- a/lib/libcxx/include/__concepts/different_from.h +++ b/lib/libcxx/include/__concepts/different_from.h @@ -19,12 +19,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -template +template concept __different_from = !same_as, remove_cvref_t<_Up>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/equality_comparable.h b/lib/libcxx/include/__concepts/equality_comparable.h index b865141705..278fc76409 100644 --- a/lib/libcxx/include/__concepts/equality_comparable.h +++ b/lib/libcxx/include/__concepts/equality_comparable.h @@ -21,33 +21,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.equalitycomparable] -template +template concept __weakly_equality_comparable_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t == __u } -> __boolean_testable; - { __t != __u } -> __boolean_testable; - { __u == __t } -> __boolean_testable; - { __u != __t } -> __boolean_testable; - }; + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; -template +template concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; -template +// clang-format off +template concept equality_comparable_with = - equality_comparable<_Tp> && equality_comparable<_Up> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && - equality_comparable< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __weakly_equality_comparable_with<_Tp, _Up>; + equality_comparable<_Tp> && equality_comparable<_Up> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + equality_comparable< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __weakly_equality_comparable_with<_Tp, _Up>; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/invocable.h b/lib/libcxx/include/__concepts/invocable.h index ec39b7b817..e5be514b5c 100644 --- a/lib/libcxx/include/__concepts/invocable.h +++ b/lib/libcxx/include/__concepts/invocable.h @@ -19,21 +19,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.invocable] -template +template concept invocable = requires(_Fn&& __fn, _Args&&... __args) { _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving }; // [concept.regular.invocable] -template +template concept regular_invocable = invocable<_Fn, _Args...>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/movable.h b/lib/libcxx/include/__concepts/movable.h index 749b78ad10..bc5b9d767c 100644 --- a/lib/libcxx/include/__concepts/movable.h +++ b/lib/libcxx/include/__concepts/movable.h @@ -21,18 +21,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.object] -template -concept movable = - is_object_v<_Tp> && - move_constructible<_Tp> && - assignable_from<_Tp&, _Tp> && - swappable<_Tp>; +template +concept movable = is_object_v<_Tp> && move_constructible<_Tp> && assignable_from<_Tp&, _Tp> && swappable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/predicate.h b/lib/libcxx/include/__concepts/predicate.h index 7ae9783264..00731efc8f 100644 --- a/lib/libcxx/include/__concepts/predicate.h +++ b/lib/libcxx/include/__concepts/predicate.h @@ -20,15 +20,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.predicate] -template -concept predicate = - regular_invocable<_Fn, _Args...> && __boolean_testable>; +template +concept predicate = regular_invocable<_Fn, _Args...> && __boolean_testable>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/regular.h b/lib/libcxx/include/__concepts/regular.h index d15728d298..9f3d8bf30b 100644 --- a/lib/libcxx/include/__concepts/regular.h +++ b/lib/libcxx/include/__concepts/regular.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.object] -template +template concept regular = semiregular<_Tp> && equality_comparable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/relation.h b/lib/libcxx/include/__concepts/relation.h index 7d5141cac7..7545a7db93 100644 --- a/lib/libcxx/include/__concepts/relation.h +++ b/lib/libcxx/include/__concepts/relation.h @@ -18,26 +18,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.relation] -template +template concept relation = - predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && - predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; + predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; // [concept.equiv] -template +template concept equivalence_relation = relation<_Rp, _Tp, _Up>; // [concept.strictweakorder] -template +template concept strict_weak_order = relation<_Rp, _Tp, _Up>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/same_as.h b/lib/libcxx/include/__concepts/same_as.h index 554ebc3b07..4241131c70 100644 --- a/lib/libcxx/include/__concepts/same_as.h +++ b/lib/libcxx/include/__concepts/same_as.h @@ -18,17 +18,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.same] -template +template concept __same_as_impl = _IsSame<_Tp, _Up>::value; -template +template concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/semiregular.h b/lib/libcxx/include/__concepts/semiregular.h index d15bb3ba42..7a159d17df 100644 --- a/lib/libcxx/include/__concepts/semiregular.h +++ b/lib/libcxx/include/__concepts/semiregular.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.object] -template +template concept semiregular = copyable<_Tp> && default_initializable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__concepts/swappable.h b/lib/libcxx/include/__concepts/swappable.h index d91a7a1dc3..c1969de345 100644 --- a/lib/libcxx/include/__concepts/swappable.h +++ b/lib/libcxx/include/__concepts/swappable.h @@ -28,94 +28,96 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.swappable] namespace ranges { namespace __swap { - template - void swap(_Tp&, _Tp&) = delete; +template +void swap(_Tp&, _Tp&) = delete; - template - concept __unqualified_swappable_with = +// clang-format off +template +concept __unqualified_swappable_with = (__class_or_enum> || __class_or_enum>) && requires(_Tp&& __t, _Up&& __u) { - swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); }; +// clang-format on - struct __fn; +struct __fn; - template - concept __swappable_arrays = - !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> && +// clang-format off +template +concept __swappable_arrays = + !__unqualified_swappable_with<_Tp (&)[_Size], _Up (&)[_Size]> && extent_v<_Tp> == extent_v<_Up> && - requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) { - __swap(__t[0], __u[0]); + requires(_Tp (&__t)[_Size], _Up (&__u)[_Size], const __fn& __swap) { + __swap(__t[0], __u[0]); }; +// clang-format on - template - concept __exchangeable = - !__unqualified_swappable_with<_Tp&, _Tp&> && - move_constructible<_Tp> && - assignable_from<_Tp&, _Tp>; +template +concept __exchangeable = + !__unqualified_swappable_with<_Tp&, _Tp&> && move_constructible<_Tp> && assignable_from<_Tp&, _Tp>; - struct __fn { - // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... - // *The name `swap` is used here unqualified. - template - requires __unqualified_swappable_with<_Tp, _Up> - constexpr void operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) - { - swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); +struct __fn { + // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... + // *The name `swap` is used here unqualified. + template + requires __unqualified_swappable_with<_Tp, _Up> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) { + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + } + + // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... + template + requires __swappable_arrays<_Tp, _Up, _Size> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp (&__t)[_Size], _Up (&__u)[_Size]) const + noexcept(noexcept((*this)(*__t, *__u))) { + // TODO(cjdb): replace with `ranges::swap_ranges`. + for (size_t __i = 0; __i < _Size; ++__i) { + (*this)(__t[__i], __u[__i]); } + } - // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... - template - requires __swappable_arrays<_Tp, _Up, _Size> - constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const - noexcept(noexcept((*this)(*__t, *__u))) - { - // TODO(cjdb): replace with `ranges::swap_ranges`. - for (size_t __i = 0; __i < _Size; ++__i) { - (*this)(__t[__i], __u[__i]); - } - } - - // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... - template<__exchangeable _Tp> - constexpr void operator()(_Tp& __x, _Tp& __y) const - noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>) - { - __y = _VSTD::exchange(__x, _VSTD::move(__y)); - } - }; + // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... + template <__exchangeable _Tp> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp& __x, _Tp& __y) const + noexcept(is_nothrow_move_constructible_v<_Tp>&& is_nothrow_move_assignable_v<_Tp>) { + __y = _VSTD::exchange(__x, _VSTD::move(__y)); + } +}; } // namespace __swap inline namespace __cpo { - inline constexpr auto swap = __swap::__fn{}; +inline constexpr auto swap = __swap::__fn{}; } // namespace __cpo } // namespace ranges -template +template concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; -template -concept swappable_with = - common_reference_with<_Tp, _Up> && - requires(_Tp&& __t, _Up&& __u) { - ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); - ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); - ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); - ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); - }; +template +concept swappable_with = common_reference_with<_Tp, _Up> && requires(_Tp&& __t, _Up&& __u) { + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); +}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___CONCEPTS_SWAPPABLE_H diff --git a/lib/libcxx/include/__concepts/totally_ordered.h b/lib/libcxx/include/__concepts/totally_ordered.h index f12d26b108..186c3b430d 100644 --- a/lib/libcxx/include/__concepts/totally_ordered.h +++ b/lib/libcxx/include/__concepts/totally_ordered.h @@ -21,37 +21,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.totallyordered] -template -concept __partially_ordered_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t < __u } -> __boolean_testable; - { __t > __u } -> __boolean_testable; - { __t <= __u } -> __boolean_testable; - { __t >= __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - { __u > __t } -> __boolean_testable; - { __u <= __t } -> __boolean_testable; - { __u >= __t } -> __boolean_testable; - }; +template +concept __partially_ordered_with = requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; +}; -template +template concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; -template +// clang-format off +template concept totally_ordered_with = - totally_ordered<_Tp> && totally_ordered<_Up> && - equality_comparable_with<_Tp, _Up> && - totally_ordered< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __partially_ordered_with<_Tp, _Up>; + totally_ordered<_Tp> && totally_ordered<_Up> && + equality_comparable_with<_Tp, _Up> && + totally_ordered< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __partially_ordered_with<_Tp, _Up>; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__condition_variable/condition_variable.h b/lib/libcxx/include/__condition_variable/condition_variable.h new file mode 100644 index 0000000000..7cbf21fe73 --- /dev/null +++ b/lib/libcxx/include/__condition_variable/condition_variable.h @@ -0,0 +1,245 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONDITION_VARIABLE_CONDITION_VARIABLE_H +#define _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H + +#include <__chrono/steady_clock.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__mutex/mutex.h> +#include <__mutex/unique_lock.h> +#include <__system_error/system_error.h> +#include <__threading_support> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_floating_point.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +// enum class cv_status +_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; + +# ifdef _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 defined(_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_NO_THREADS + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, chrono::nanoseconds> +__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { + using namespace chrono; + using __ratio = ratio_divide<_Period, nano>; + using __ns_rep = nanoseconds::rep; + _Rep __result_float = __d.count() * __ratio::num / __ratio::den; + + _Rep __result_max = numeric_limits<__ns_rep>::max(); + if (__result_float >= __result_max) { + return nanoseconds::max(); + } + + _Rep __result_min = numeric_limits<__ns_rep>::min(); + if (__result_float <= __result_min) { + return nanoseconds::min(); + } + + return nanoseconds(static_cast<__ns_rep>(__result_float)); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, chrono::nanoseconds> +__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { + using namespace chrono; + if (__d.count() == 0) { + return nanoseconds(0); + } + + using __ratio = ratio_divide<_Period, nano>; + using __ns_rep = nanoseconds::rep; + __ns_rep __result_max = numeric_limits<__ns_rep>::max(); + if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { + return nanoseconds::max(); + } + + __ns_rep __result_min = numeric_limits<__ns_rep>::min(); + if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { + return nanoseconds::min(); + } + + __ns_rep __result = __d.count() * __ratio::num / __ratio::den; + if (__result == 0) { + return nanoseconds(1); + } + + return nanoseconds(__result); +} + +#ifndef _LIBCPP_HAS_NO_THREADS +template +void condition_variable::wait(unique_lock& __lk, _Predicate __pred) { + while (!__pred()) + wait(__lk); +} + +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>; + + 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 defined(_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 +inline bool +condition_variable::wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) { + return wait_until(__lk, chrono::steady_clock::now() + __d, std::move(__pred)); +} + +# if defined(_LIBCPP_HAS_COND_CLOCKWAIT) +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"); + nanoseconds __d = __tp.time_since_epoch(); + timespec __ts; + seconds __s = duration_cast(__d); + using __ts_sec = decltype(__ts.tv_sec); + const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); + if (__s.count() < __ts_sec_max) { + __ts.tv_sec = static_cast<__ts_sec>(__s.count()); + __ts.tv_nsec = (__d - __s).count(); + } else { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = giga::num - 1; + } + 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"); +} +# endif // _LIBCPP_HAS_COND_CLOCKWAIT + +template +inline void condition_variable::__do_timed_wait(unique_lock& __lk, + chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT { + wait_for(__lk, __tp - _Clock::now()); +} + +#endif // _LIBCPP_HAS_NO_THREADS + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H diff --git a/lib/libcxx/include/__config b/lib/libcxx/include/__config index 7967c70035..5286165f49 100644 --- a/lib/libcxx/include/__config +++ b/lib/libcxx/include/__config @@ -35,10 +35,12 @@ #ifdef __cplusplus +// The attributes supported by clang are documented at https://clang.llvm.org/docs/AttributeReference.html + // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. -// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is +// 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 160001 +# define _LIBCPP_VERSION 170000 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -51,6 +53,7 @@ # define _LIBCPP_FREESTANDING # endif +// NOLINTBEGIN(libcpp-cpp-version-check) # ifndef _LIBCPP_STD_VER # if __cplusplus <= 201103L # define _LIBCPP_STD_VER 11 @@ -60,11 +63,14 @@ # define _LIBCPP_STD_VER 17 # elif __cplusplus <= 202002L # define _LIBCPP_STD_VER 20 +# elif __cplusplus <= 202302L +# define _LIBCPP_STD_VER 23 # else // Expected release year of the next C++ standard -# define _LIBCPP_STD_VER 23 +# define _LIBCPP_STD_VER 26 # endif # endif // _LIBCPP_STD_VER +// NOLINTEND(libcpp-cpp-version-check) # if defined(__ELF__) # define _LIBCPP_OBJECT_FORMAT_ELF 1 @@ -80,6 +86,8 @@ // ... add new file formats here ... # endif +// ABI { + # if _LIBCPP_ABI_VERSION >= 2 // Change short string representation so that string data starts at offset 0, // improving its alignment in some cases. @@ -165,6 +173,12 @@ # if defined(__FreeBSD__) # define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR # endif +// For XCOFF linkers, we have problems if we see a weak hidden version of a symbol +// in user code (like you get with -fvisibility-inlines-hidden) and then a strong def +// in the library, so we need to always rely on the library version. +# if defined(_AIX) +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +# endif # endif # if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2 @@ -179,9 +193,137 @@ # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION # endif +// 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`; +// - `array`. +// #define _LIBCPP_ABI_BOUNDED_ITERATORS + +// } ABI + +// HARDENING { + +// TODO(hardening): remove this in LLVM 18. +// This is for backward compatibility -- make enabling `_LIBCPP_ENABLE_ASSERTIONS` (which predates hardening modes) +// equivalent to setting the hardened mode. +# ifdef _LIBCPP_ENABLE_ASSERTIONS +# warning "_LIBCPP_ENABLE_ASSERTIONS is deprecated, please use _LIBCPP_ENABLE_HARDENED_MODE instead." +# if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 +# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" +# endif +# if _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_HARDENED_MODE 1 +# endif +# endif + +// Enables the hardened mode which consists of all checks intended to be used in production. Hardened mode prioritizes +// security-critical checks that can be done with relatively little overhead in constant time. Mutually exclusive with +// `_LIBCPP_ENABLE_DEBUG_MODE`. +// +// #define _LIBCPP_ENABLE_HARDENED_MODE 1 + +// Enables the debug mode which contains all the checks from the hardened mode and additionally more expensive checks +// that may affect the complexity of algorithms. The debug mode is intended to be used for testing, not in production. +// Mutually exclusive with `_LIBCPP_ENABLE_HARDENED_MODE`. +// +// #define _LIBCPP_ENABLE_DEBUG_MODE 1 + +// Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These +// macros are only for internal use -- users should only pick one of the high-level hardening modes described above. +// +// - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and +// a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid: +// - the sentinel is reachable from the begin iterator; +// - TODO(hardening): both iterators refer to the same container. +// +// - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through +// the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access +// a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like +// `optional` and `function` are considered one-element containers for the purposes of this check. +// +// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the +// given ranges do not overlap. +// +// - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure +// the containers have compatible allocators. +// +// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on +// user input. +// +// - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet. + +# ifndef _LIBCPP_ENABLE_HARDENED_MODE +# define _LIBCPP_ENABLE_HARDENED_MODE _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT +# endif +# if _LIBCPP_ENABLE_HARDENED_MODE != 0 && _LIBCPP_ENABLE_HARDENED_MODE != 1 +# error "_LIBCPP_ENABLE_HARDENED_MODE must be set to 0 or 1." +# endif + +# ifndef _LIBCPP_ENABLE_DEBUG_MODE +# define _LIBCPP_ENABLE_DEBUG_MODE _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT +# endif +# if _LIBCPP_ENABLE_DEBUG_MODE != 0 && _LIBCPP_ENABLE_DEBUG_MODE != 1 +# error "_LIBCPP_ENABLE_DEBUG_MODE must be set to 0 or 1." +# endif + +# if _LIBCPP_ENABLE_HARDENED_MODE && _LIBCPP_ENABLE_DEBUG_MODE +# error "Only one of _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_DEBUG_MODE can be enabled." +# endif + +// Hardened mode checks. + +// clang-format off +# if _LIBCPP_ENABLE_HARDENED_MODE + +// Enabled checks. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +// Disabled checks. +// Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security +// vulnerability. +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) + +// Debug mode checks. + +# elif _LIBCPP_ENABLE_DEBUG_MODE + +// All checks enabled. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message) + +// Disable all checks if hardening is not enabled. + +# else + +// All checks disabled. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) + +# endif // _LIBCPP_ENABLE_HARDENED_MODE +// clang-format on + +// } 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 @@ -262,7 +404,11 @@ // 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_NO_INCOMPLETE_FORMAT +# define _LIBCPP_HAS_NO_INCOMPLETE_PSTL +# endif + +# if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN # endif // Need to detect which libc we're using if we're on Linux. @@ -300,8 +446,8 @@ # endif // __BYTE_ORDER__ # ifdef __FreeBSD__ -# include # include +# include # if _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN # else // _BYTE_ORDER == _LITTLE_ENDIAN @@ -335,15 +481,6 @@ # define _LIBCPP_HAS_OPEN_WITH_WCHAR # endif // defined(_WIN32) -# ifdef __sun__ -# include -# ifdef _LITTLE_ENDIAN -# define _LIBCPP_LITTLE_ENDIAN -# else -# define _LIBCPP_BIG_ENDIAN -# endif -# endif // __sun__ - # if defined(_AIX) && !defined(__64BIT__) // The size of wchar is 2 byte on 32-bit mode on AIX. # define _LIBCPP_SHORT_WCHAR 1 @@ -388,7 +525,7 @@ // When this option is used, the token passed to `std::random_device`'s // constructor *must* be "/dev/urandom" -- anything else is an error. # if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ - defined(__DragonFly__) || defined(__sun__) + defined(__DragonFly__) # define _LIBCPP_USING_ARC4_RANDOM # elif defined(__wasi__) || defined(__EMSCRIPTEN__) # define _LIBCPP_USING_GETENTROPY @@ -449,15 +586,24 @@ typedef __char32_t char32_t; # endif # if !defined(__cpp_exceptions) || __cpp_exceptions < 199711L -# define _LIBCPP_NO_EXCEPTIONS +# define _LIBCPP_HAS_NO_EXCEPTIONS # endif # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) # if defined(_LIBCPP_COMPILER_CLANG_BASED) -# if defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && (!defined(__arm__) || __ARM_ARCH_7K__ >= 2) -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# if defined(__APPLE__) +# if defined(__i386__) || defined(__x86_64__) +// use old string layout on x86_64 and i386 +# elif defined(__arm__) +// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs +# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2 +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif +# else +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif # endif // Objective-C++ features (opt-in) @@ -535,9 +681,6 @@ typedef __char32_t char32_t; # define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport) # endif -# define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS -# define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS -# define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS # define _LIBCPP_HIDDEN # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # define _LIBCPP_TEMPLATE_VIS @@ -553,11 +696,8 @@ typedef __char32_t char32_t; # endif # define _LIBCPP_HIDDEN _LIBCPP_VISIBILITY("hidden") -# define _LIBCPP_FUNC_VIS _LIBCPP_VISIBILITY("default") -# define _LIBCPP_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_TEMPLATE_DATA_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default") -# define _LIBCPP_EXCEPTION_ABI _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS @@ -666,7 +806,7 @@ typedef __char32_t char32_t; _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { # else @@ -683,16 +823,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_PREFERRED_OVERLOAD __attribute__((__enable_if__(true, ""))) # endif -# ifndef __SIZEOF_INT128__ +# if !defined(__SIZEOF_INT128__) || defined(_MSC_VER) # define _LIBCPP_HAS_NO_INT128 # endif -# ifndef __cpp_consteval -# define _LIBCPP_CONSTEVAL _LIBCPP_CONSTEXPR -# else -# define _LIBCPP_CONSTEVAL consteval -# endif - # if __has_attribute(__malloc__) # define _LIBCPP_NOALIAS __attribute__((__malloc__)) # else @@ -707,7 +841,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # ifdef _LIBCPP_CXX03_LANG # define _LIBCPP_DECLARE_STRONG_ENUM(x) \ - struct _LIBCPP_TYPE_VIS x { \ + struct _LIBCPP_EXPORTED_FROM_ABI x { \ enum __lx // clang-format off # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ @@ -723,8 +857,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) # endif // _LIBCPP_CXX03_LANG -# if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || defined(__sun__) || \ - defined(__NetBSD__) +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || defined(__NetBSD__) # define _LIBCPP_LOCALE__L_EXTENSIONS 1 # endif @@ -764,7 +897,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_HAS_DEFAULTRUNELOCALE # endif -# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) +# if defined(__APPLE__) || defined(__FreeBSD__) # define _LIBCPP_WCTYPE_IS_MASK # endif @@ -777,10 +910,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // Deprecations warnings are always enabled, except when users explicitly opt-out // by defining _LIBCPP_DISABLE_DEPRECATION_WARNINGS. # if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# if __has_attribute(deprecated) -# define _LIBCPP_DEPRECATED __attribute__((deprecated)) -# define _LIBCPP_DEPRECATED_(m) __attribute__((deprecated(m))) -# elif _LIBCPP_STD_VER > 11 +# if __has_attribute(__deprecated__) +# define _LIBCPP_DEPRECATED __attribute__((__deprecated__)) +# define _LIBCPP_DEPRECATED_(m) __attribute__((__deprecated__(m))) +# elif _LIBCPP_STD_VER >= 14 # define _LIBCPP_DEPRECATED [[deprecated]] # define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]] # else @@ -798,29 +931,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DEPRECATED_IN_CXX11 # endif -# if _LIBCPP_STD_VER > 11 +# if _LIBCPP_STD_VER >= 14 # define _LIBCPP_DEPRECATED_IN_CXX14 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX14 # endif -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX17 # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX20 # endif -#if _LIBCPP_STD_VER >= 23 -# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED -#else -# define _LIBCPP_DEPRECATED_IN_CXX23 -#endif +# if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX23 +# endif # if !defined(_LIBCPP_HAS_NO_CHAR8_T) # define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED @@ -840,37 +973,43 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # endif # if _LIBCPP_STD_VER <= 11 -# define _LIBCPP_EXPLICIT_AFTER_CXX11 +# define _LIBCPP_EXPLICIT_SINCE_CXX14 # else -# define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit +# define _LIBCPP_EXPLICIT_SINCE_CXX14 explicit # endif -# if _LIBCPP_STD_VER > 11 +# if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_EXPLICIT_SINCE_CXX23 explicit +# else +# define _LIBCPP_EXPLICIT_SINCE_CXX23 +# endif + +# if _LIBCPP_STD_VER >= 14 # define _LIBCPP_CONSTEXPR_SINCE_CXX14 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX14 # endif -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_CONSTEXPR_SINCE_CXX17 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX17 # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTEXPR_SINCE_CXX20 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX20 # endif -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 # define _LIBCPP_CONSTEXPR_SINCE_CXX23 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX23 # endif # if __has_cpp_attribute(nodiscard) -# define _LIBCPP_NODISCARD [[nodiscard]] +# define _LIBCPP_NODISCARD [[__nodiscard__]] # else // We can't use GCC's [[gnu::warn_unused_result]] and // __attribute__((warn_unused_result)), because GCC does not silence them via @@ -886,7 +1025,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_NODISCARD_EXT # endif -# if _LIBCPP_STD_VER > 17 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) # define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD # else # define _LIBCPP_NODISCARD_AFTER_CXX17 @@ -899,8 +1038,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # endif # ifndef _LIBCPP_HAS_NO_ASAN - extern "C" _LIBCPP_FUNC_VIS void + extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); +# if _LIBCPP_CLANG_VER >= 1600 +extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*); +extern "C" _LIBCPP_EXPORTED_FROM_ABI int +__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); +# endif # endif // Try to find out if RTTI is disabled. @@ -927,7 +1072,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD defined(__linux__) || \ defined(__GNU__) || \ defined(__APPLE__) || \ - defined(__sun__) || \ defined(__MVS__) || \ defined(_AIX) || \ defined(__EMSCRIPTEN__) @@ -1034,6 +1178,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif +# if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(__no_thread_safety_analysis__) +# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((__no_thread_safety_analysis__)) +# else +# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS +# endif + # if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) # if defined(__clang__) && __has_attribute(acquire_capability) // Work around the attribute handling in clang. When both __declspec and @@ -1052,7 +1202,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTINIT constinit # elif __has_attribute(__require_constant_initialization__) # define _LIBCPP_CONSTINIT __attribute__((__require_constant_initialization__)) @@ -1099,6 +1249,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_PREFERRED_NAME(x) # endif +# if __has_attribute(__no_sanitize__) +# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# else +# define _LIBCPP_NO_SANITIZE(...) +# endif + // We often repeat things just for handling wide characters in the library. // When wide characters are disabled, it can be useful to have a quick way of // disabling it without having to resort to #if-#endif, which has a larger @@ -1132,8 +1288,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS # endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES -# define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") -# define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") +// clang-format off +# define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") _Pragma("push_macro(\"refresh()\")") _Pragma("push_macro(\"move(int, int)\")") _Pragma("push_macro(\"erase()\")") +# define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") _Pragma("pop_macro(\"refresh()\")") _Pragma("pop_macro(\"move(int, int)\")") _Pragma("pop_macro(\"erase()\")") +// clang-format on # ifndef _LIBCPP_NO_AUTO_LINK # if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) @@ -1189,7 +1347,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // [[msvc::no_unique_address]], this should be preferred though. # define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] # elif __has_cpp_attribute(no_unique_address) -# define _LIBCPP_NO_UNIQUE_ADDRESS [[no_unique_address]] +# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]] # else # define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */ // Note that this can be replaced by #error as soon as clang-cl @@ -1252,13 +1410,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // macro is used to mark them as such, which suppresses the // '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code // with these classes. -#if _LIBCPP_STD_VER >= 17 -# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ - template \ - _ClassName(typename _Tag::__allow_ctad...) -> _ClassName<_Tag...> -#else -# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") -#endif +# if _LIBCPP_STD_VER >= 17 +# ifdef _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ + template \ + [[maybe_unused]] _ClassName(typename _Tag::__allow_ctad...)->_ClassName<_Tag...> +# else +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(ClassName) \ + template \ + ClassName(typename _Tag::__allow_ctad...)->ClassName<_Tag...> +# endif +# else +# 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. @@ -1266,6 +1430,43 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS # endif +# define _PSTL_PRAGMA(x) _Pragma(#x) + +// Enable SIMD for compilers that support OpenMP 4.0 +# if (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_UDR_PRESENT +# define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd) +# define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd) +# define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) _PSTL_PRAGMA(omp simd reduction(PRM)) +# define _PSTL_PRAGMA_SIMD_SCAN(PRM) _PSTL_PRAGMA(omp simd reduction(inscan, PRM)) +# define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan inclusive(PRM)) +# define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan exclusive(PRM)) + +// Declaration of reduction functor, where +// NAME - the name of the functor +// OP - type of the callable object with the reduction operation +// omp_in - refers to the local partial result +// omp_out - refers to the final value of the combiner operator +// omp_priv - refers to the private copy of the initial value +// omp_orig - refers to the original variable to be reduced +# define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) \ + _PSTL_PRAGMA(omp declare reduction(NAME:OP : omp_out(omp_in)) initializer(omp_priv = omp_orig)) + +# else // (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_PRAGMA_SIMD +# define _PSTL_PRAGMA_DECLARE_SIMD +# define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) +# define _PSTL_PRAGMA_SIMD_SCAN(PRM) +# define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) + +# endif // (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/lib/libcxx/include/__coroutine/coroutine_handle.h b/lib/libcxx/include/__coroutine/coroutine_handle.h index 0a6cc1cab6..7a4eff745e 100644 --- a/lib/libcxx/include/__coroutine/coroutine_handle.h +++ b/lib/libcxx/include/__coroutine/coroutine_handle.h @@ -21,7 +21,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,7 +33,6 @@ template <> struct _LIBCPP_TEMPLATE_VIS coroutine_handle { public: // [coroutine.handle.con], construct/reset - _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle() noexcept = default; _LIBCPP_HIDE_FROM_ABI @@ -64,7 +63,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool done() const { - _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "done() can be called only on suspended coroutines"); return __builtin_coro_done(__handle_); } @@ -74,19 +73,19 @@ public: _LIBCPP_HIDE_FROM_ABI void resume() const { - _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); - _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(!done(), "resume() has undefined behavior when the coroutine is done"); __builtin_coro_resume(__handle_); } _LIBCPP_HIDE_FROM_ABI void destroy() const { - _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "destroy() can be called only on suspended coroutines"); __builtin_coro_destroy(__handle_); } private: - bool __is_suspended() const { + _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { // FIXME actually implement a check for if the coro is suspended. return __handle_ != nullptr; } @@ -108,7 +107,6 @@ template struct _LIBCPP_TEMPLATE_VIS coroutine_handle { public: // [coroutine.handle.con], construct/reset - _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle() noexcept = default; _LIBCPP_HIDE_FROM_ABI @@ -154,7 +152,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool done() const { - _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "done() can be called only on suspended coroutines"); return __builtin_coro_done(__handle_); } @@ -164,14 +162,14 @@ public: _LIBCPP_HIDE_FROM_ABI void resume() const { - _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); - _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(!done(), "resume() has undefined behavior when the coroutine is done"); __builtin_coro_resume(__handle_); } _LIBCPP_HIDE_FROM_ABI void destroy() const { - _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "destroy() can be called only on suspended coroutines"); __builtin_coro_destroy(__handle_); } @@ -182,7 +180,7 @@ public: } private: - bool __is_suspended() const { + _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { // FIXME actually implement a check for if the coro is suspended. return __handle_ != nullptr; } @@ -198,6 +196,6 @@ struct hash> { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#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 d513075098..7122cc8ea8 100644 --- a/lib/libcxx/include/__coroutine/coroutine_traits.h +++ b/lib/libcxx/include/__coroutine/coroutine_traits.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -48,6 +48,6 @@ struct coroutine_traits _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#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 299304794c..9b7802d1e2 100644 --- a/lib/libcxx/include/__coroutine/noop_coroutine_handle.h +++ b/lib/libcxx/include/__coroutine/noop_coroutine_handle.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -107,6 +107,6 @@ noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle() _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#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 bbbae7a47f..0e4b08e377 100644 --- a/lib/libcxx/include/__coroutine/trivial_awaitables.h +++ b/lib/libcxx/include/__coroutine/trivial_awaitables.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,6 +41,6 @@ struct suspend_always { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#endif // __LIBCPP_STD_VER >= 20 #endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/lib/libcxx/include/__debug b/lib/libcxx/include/__debug deleted file mode 100644 index 140cc9142a..0000000000 --- a/lib/libcxx/include/__debug +++ /dev/null @@ -1,266 +0,0 @@ -// -*- 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___DEBUG -#define _LIBCPP___DEBUG - -#include <__assert> -#include <__config> -#include <__type_traits/is_constant_evaluated.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) -# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING) -# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING -#endif - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE -# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m) -#else -# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) - -_LIBCPP_BEGIN_NAMESPACE_STD - -struct _LIBCPP_TYPE_VIS __c_node; - -struct _LIBCPP_TYPE_VIS __i_node -{ - void* __i_; - __i_node* __next_; - __c_node* __c_; - - __i_node(const __i_node&) = delete; - __i_node& operator=(const __i_node&) = delete; - - _LIBCPP_INLINE_VISIBILITY - __i_node(void* __i, __i_node* __next, __c_node* __c) - : __i_(__i), __next_(__next), __c_(__c) {} - ~__i_node(); -}; - -struct _LIBCPP_TYPE_VIS __c_node -{ - void* __c_; - __c_node* __next_; - __i_node** beg_; - __i_node** end_; - __i_node** cap_; - - __c_node(const __c_node&) = delete; - __c_node& operator=(const __c_node&) = delete; - - _LIBCPP_INLINE_VISIBILITY - explicit __c_node(void* __c, __c_node* __next) - : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} - virtual ~__c_node(); - - virtual bool __dereferenceable(const void*) const = 0; - virtual bool __decrementable(const void*) const = 0; - virtual bool __addable(const void*, ptrdiff_t) const = 0; - virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; - - void __add(__i_node* __i); - _LIBCPP_HIDDEN void __remove(__i_node* __i); -}; - -template -struct _C_node - : public __c_node -{ - explicit _C_node(void* __c, __c_node* __n) - : __c_node(__c, __n) {} - - bool __dereferenceable(const void*) const override; - bool __decrementable(const void*) const override; - bool __addable(const void*, ptrdiff_t) const override; - bool __subscriptable(const void*, ptrdiff_t) const override; -}; - -template -inline bool -_C_node<_Cont>::__dereferenceable(const void* __i) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__dereferenceable(__j); -} - -template -inline bool -_C_node<_Cont>::__decrementable(const void* __i) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__decrementable(__j); -} - -template -inline bool -_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__addable(__j, __n); -} - -template -inline bool -_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__subscriptable(__j, __n); -} - -class _LIBCPP_TYPE_VIS __libcpp_db -{ - __c_node** __cbeg_; - __c_node** __cend_; - size_t __csz_; - __i_node** __ibeg_; - __i_node** __iend_; - size_t __isz_; - - explicit __libcpp_db(); -public: - __libcpp_db(const __libcpp_db&) = delete; - __libcpp_db& operator=(const __libcpp_db&) = delete; - - ~__libcpp_db(); - - class __db_c_iterator; - class __db_c_const_iterator; - class __db_i_iterator; - class __db_i_const_iterator; - - __db_c_const_iterator __c_end() const; - __db_i_const_iterator __i_end() const; - - typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*); - - template - _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) { - return ::new (__mem) _C_node<_Cont>(__c, __next); - } - - template - _LIBCPP_INLINE_VISIBILITY - void __insert_c(_Cont* __c) - { - __insert_c(static_cast(__c), &__create_C_node<_Cont>); - } - - void __insert_i(void* __i); - void __insert_c(void* __c, _InsertConstruct* __fn); - void __erase_c(void* __c); - - void __insert_ic(void* __i, const void* __c); - void __iterator_copy(void* __i, const void* __i0); - void __erase_i(void* __i); - - void* __find_c_from_i(void* __i) const; - void __invalidate_all(void* __c); - __c_node* __find_c_and_lock(void* __c) const; - __c_node* __find_c(void* __c) const; - void unlock() const; - - void swap(void* __c1, void* __c2); - - - bool __dereferenceable(const void* __i) const; - bool __decrementable(const void* __i) const; - bool __addable(const void* __i, ptrdiff_t __n) const; - bool __subscriptable(const void* __i, ptrdiff_t __n) const; - bool __less_than_comparable(const void* __i, const void* __j) const; -private: - _LIBCPP_HIDDEN - __i_node* __insert_iterator(void* __i); - _LIBCPP_HIDDEN - __i_node* __find_iterator(const void* __i) const; - - friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); -}; - -_LIBCPP_FUNC_VIS __libcpp_db* __get_db(); -_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); - -_LIBCPP_END_NAMESPACE_STD - -#endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_c(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_c(__c); -#else - (void)(__c); -#endif -} - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_i(_Tp* __i) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_i(__i); -#else - (void)(__i); -#endif -} - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_erase_c(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__erase_c(__c); -#else - (void)(__c); -#endif -} - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->swap(__lhs, __rhs); -#else - (void)(__lhs); - (void)(__rhs); -#endif -} - -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_invalidate_all(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__invalidate_all(__c); -#else - (void)(__c); -#endif -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___DEBUG diff --git a/lib/libcxx/include/__debug_utils/strict_weak_ordering_check.h b/lib/libcxx/include/__debug_utils/strict_weak_ordering_check.h new file mode 100644 index 0000000000..99200ad65e --- /dev/null +++ b/lib/libcxx/include/__debug_utils/strict_weak_ordering_check.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK +#define _LIBCPP___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK + +#include <__config> + +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/is_sorted.h> +#include <__assert> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_constant_evaluated.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { +#ifdef _LIBCPP_DEBUG_STRICT_WEAK_ORDERING_CHECK + using __diff_t = __iter_diff_t<_RandomAccessIterator>; + using _Comp_ref = __comp_ref_type<_Comp>; + if (!__libcpp_is_constant_evaluated()) { + // Check if the range is actually sorted. + _LIBCPP_ASSERT_UNCATEGORIZED( + (std::is_sorted<_RandomAccessIterator, _Comp_ref>(__first, __last, _Comp_ref(__comp))), + "The range is not sorted after the sort, your comparator is not a valid strict-weak ordering"); + // Limit the number of elements we need to check. + __diff_t __size = __last - __first > __diff_t(100) ? __diff_t(100) : __last - __first; + __diff_t __p = 0; + while (__p < __size) { + __diff_t __q = __p + __diff_t(1); + // Find first element that is greater than *(__first+__p). + while (__q < __size && !__comp(*(__first + __p), *(__first + __q))) { + ++__q; + } + // Check that the elements from __p to __q are equal between each other. + for (__diff_t __b = __p; __b < __q; ++__b) { + for (__diff_t __a = __p; __a <= __b; ++__a) { + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering"); + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering"); + } + } + // Check that elements between __p and __q are less than between __q and __size. + for (__diff_t __a = __p; __a < __q; ++__a) { + for (__diff_t __b = __q; __b < __size; ++__b) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering"); + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering"); + } + } + // Skip these equal elements. + __p = __q; + } + } +#else + (void)__first; + (void)__last; + (void)__comp; +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK diff --git a/lib/libcxx/include/__exception/exception.h b/lib/libcxx/include/__exception/exception.h new file mode 100644 index 0000000000..3db0126da2 --- /dev/null +++ b/lib/libcxx/include/__exception/exception.h @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// 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___EXCEPTION_EXCEPTION_H +#define _LIBCPP___EXCEPTION_EXCEPTION_H + +#include <__config> + +// defines its own std::exception and std::bad_exception types, +// which we use in order to be ABI-compatible with other STLs on Windows. +#if defined(_LIBCPP_ABI_VCRUNTIME) +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +#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. + +#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 +// However, does not define std::exception and std::bad_exception +// when _HAS_EXCEPTIONS == 0. +// +// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 +// (after all those are simply types like any other), we define an ABI-compatible version +// of the VCRuntime std::exception and std::bad_exception types in that mode. + +struct __std_exception_data { + char const* _What; + bool _DoFree; +}; + +class exception { // base of all library exceptions +public: + exception() _NOEXCEPT : __data_() {} + + explicit exception(char const* __message) _NOEXCEPT : __data_() { + __data_._What = __message; + __data_._DoFree = true; + } + + exception(exception const&) _NOEXCEPT {} + + exception& operator=(exception const&) _NOEXCEPT { return *this; } + + virtual ~exception() _NOEXCEPT {} + + virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } + +private: + __std_exception_data __data_; +}; + +class bad_exception : public exception { +public: + bad_exception() _NOEXCEPT : exception("bad exception") {} +}; + +#else // !defined(_LIBCPP_ABI_VCRUNTIME) +// On all other platforms, we define our own std::exception and std::bad_exception types +// regardless of whether exceptions are turned on as a language feature. + +class _LIBCPP_EXPORTED_FROM_ABI exception { +public: + _LIBCPP_HIDE_FROM_ABI exception() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI exception(const exception&) _NOEXCEPT = default; + + virtual ~exception() _NOEXCEPT; + virtual const char* what() const _NOEXCEPT; +}; + +class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception { +public: + _LIBCPP_HIDE_FROM_ABI bad_exception() _NOEXCEPT {} + ~bad_exception() _NOEXCEPT override; + const char* what() const _NOEXCEPT override; +}; +#endif // !_LIBCPP_ABI_VCRUNTIME + +} // 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 new file mode 100644 index 0000000000..970d819672 --- /dev/null +++ b/lib/libcxx/include/__exception/exception_ptr.h @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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___EXCEPTION_EXCEPTION_PTR_H +#define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H + +#include <__config> +#include <__exception/operations.h> +#include <__memory/addressof.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +#ifndef _LIBCPP_ABI_MICROSOFT + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { + void* __ptr_; + +public: + _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} + _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} + + exception_ptr(const exception_ptr&) _NOEXCEPT; + exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; + ~exception_ptr() _NOEXCEPT; + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return __x.__ptr_ == __y.__ptr_; + } + + friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return !(__x == __y); + } + + friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; + friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); +}; + +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { + throw __e; + } catch (...) { + return current_exception(); + } +# else + ((void)__e); + std::abort(); +# endif +} + +#else // _LIBCPP_ABI_MICROSOFT + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { + _LIBCPP_DIAGNOSTIC_PUSH + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") + void* __ptr1_; + void* __ptr2_; + _LIBCPP_DIAGNOSTIC_POP + +public: + exception_ptr() _NOEXCEPT; + exception_ptr(nullptr_t) _NOEXCEPT; + exception_ptr(const exception_ptr& __other) _NOEXCEPT; + exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; + exception_ptr& operator=(nullptr_t) _NOEXCEPT; + ~exception_ptr() _NOEXCEPT; + explicit operator bool() const _NOEXCEPT; +}; + +_LIBCPP_EXPORTED_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return !(__x == __y); +} + +_LIBCPP_EXPORTED_FROM_ABI void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; + +_LIBCPP_EXPORTED_FROM_ABI exception_ptr __copy_exception_ptr(void* __except, const void* __ptr); +_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); + +// This is a built-in template function which automagically extracts the required +// information. +template +void* __GetExceptionInfo(_E); + +template +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { + return __copy_exception_ptr(std::addressof(__e), __GetExceptionInfo(__e)); +} + +#endif // _LIBCPP_ABI_MICROSOFT +} // 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 new file mode 100644 index 0000000000..1136c92748 --- /dev/null +++ b/lib/libcxx/include/__exception/nested_exception.h @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// 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___EXCEPTION_NESTED_EXCEPTION_H +#define _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H + +#include <__config> +#include <__exception/exception_ptr.h> +#include <__memory/addressof.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_class.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_final.h> +#include <__type_traits/is_polymorphic.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +class _LIBCPP_EXPORTED_FROM_ABI nested_exception { + exception_ptr __ptr_; + +public: + nested_exception() _NOEXCEPT; + // nested_exception(const nested_exception&) noexcept = default; + // nested_exception& operator=(const nested_exception&) noexcept = default; + virtual ~nested_exception() _NOEXCEPT; + + // access functions + _LIBCPP_NORETURN void rethrow_nested() const; + _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; } +}; + +template +struct __nested : public _Tp, public nested_exception { + _LIBCPP_HIDE_FROM_ABI explicit __nested(const _Tp& __t) : _Tp(__t) {} +}; + +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS +template +struct __throw_with_nested; + +template +struct __throw_with_nested<_Tp, _Up, true> { + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) { + throw __nested<_Up>(std::forward<_Tp>(__t)); + } +}; + +template +struct __throw_with_nested<_Tp, _Up, false> { + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) { throw std::forward<_Tp>(__t); } +}; +#endif + +template +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void throw_with_nested(_Tp&& __t) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + using _Up = __decay_t<_Tp>; + static_assert(is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); + __throw_with_nested<_Tp, + _Up, + is_class<_Up>::value && !is_base_of::value && + !__libcpp_is_final<_Up>::value>::__do_throw(std::forward<_Tp>(__t)); +#else + ((void)__t); + // FIXME: Make this abort +#endif +} + +template +struct __can_dynamic_cast + : _BoolConstant< is_polymorphic<_From>::value && + (!is_base_of<_To, _From>::value || is_convertible::value)> {}; + +template +inline _LIBCPP_HIDE_FROM_ABI void +rethrow_if_nested(const _Ep& __e, __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) { + const nested_exception* __nep = dynamic_cast(std::addressof(__e)); + if (__nep) + __nep->rethrow_nested(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI void +rethrow_if_nested(const _Ep&, __enable_if_t::value>* = 0) {} + +} // namespace std + +#endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H diff --git a/lib/libcxx/include/__exception/operations.h b/lib/libcxx/include/__exception/operations.h new file mode 100644 index 0000000000..78e7c7a5d0 --- /dev/null +++ b/lib/libcxx/include/__exception/operations.h @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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___EXCEPTION_OPERATIONS_H +#define _LIBCPP___EXCEPTION_OPERATIONS_H + +#include <__availability> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) || \ + defined(_LIBCPP_BUILDING_LIBRARY) +using unexpected_handler = void (*)(); +_LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void unexpected(); +#endif + +using terminate_handler = void (*)(); +_LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT; + +_LIBCPP_EXPORTED_FROM_ABI bool uncaught_exception() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr; + +_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); +} // namespace std + +#endif // _LIBCPP___EXCEPTION_OPERATIONS_H diff --git a/lib/libcxx/include/__exception/terminate.h b/lib/libcxx/include/__exception/terminate.h new file mode 100644 index 0000000000..e672471dc5 --- /dev/null +++ b/lib/libcxx/include/__exception/terminate.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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___EXCEPTION_TERMINATE_H +#define _LIBCPP___EXCEPTION_TERMINATE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void terminate() _NOEXCEPT; +} // namespace std + +#endif // _LIBCPP___EXCEPTION_TERMINATE_H diff --git a/lib/libcxx/include/__expected/bad_expected_access.h b/lib/libcxx/include/__expected/bad_expected_access.h index 361eab4b60..27f01d9350 100644 --- a/lib/libcxx/include/__expected/bad_expected_access.h +++ b/lib/libcxx/include/__expected/bad_expected_access.h @@ -10,14 +10,16 @@ #define _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H #include <__config> +#include <__exception/exception.h> #include <__utility/move.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 @@ -33,14 +35,14 @@ protected: _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default; _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default; _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default; - ~bad_expected_access() override = default; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default; public: // The way this has been designed (by using a class template below) means that we'll already // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch // of work to do. So it is not worth hiding the specialization in the dylib, given that // it adds deployment target restrictions. - const char* what() const noexcept override { return "bad access to std::expected"; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { return "bad access to std::expected"; } }; template @@ -61,4 +63,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H diff --git a/lib/libcxx/include/__expected/expected.h b/lib/libcxx/include/__expected/expected.h index ca3e8a5992..7d57aa4db5 100644 --- a/lib/libcxx/include/__expected/expected.h +++ b/lib/libcxx/include/__expected/expected.h @@ -14,10 +14,12 @@ #include <__expected/bad_expected_access.h> #include <__expected/unexpect.h> #include <__expected/unexpected.h> +#include <__functional/invoke.h> #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/conjunction.h> #include <__type_traits/disjunction.h> +#include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -44,36 +46,48 @@ #include <__type_traits/negation.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> +#include <__utility/as_const.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/swap.h> -#include // for std::abort +#include <__verbose_abort> #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 -namespace __expected { +template +class expected; + +template +struct __is_std_expected : false_type {}; + +template +struct __is_std_expected> : true_type {}; + +struct __expected_construct_in_place_from_invoke_tag {}; +struct __expected_construct_unexpected_from_invoke_tag {}; template _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { -# ifndef _LIBCPP_NO_EXCEPTIONS +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); # else (void)__arg; - std::abort(); + _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode"); # endif } -} // namespace __expected - template class expected { static_assert( @@ -166,6 +180,15 @@ private: _Not, const expected<_Up, _OtherErr>&>>, _Not, const expected<_Up, _OtherErr>>> >; + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} public: template @@ -503,32 +526,32 @@ public: // [expected.object.obs], observers _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } @@ -537,50 +560,56 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { + static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, + "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { + static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, + "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } @@ -598,6 +627,245 @@ public: return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); } + template + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) + return std::forward<_Up>(__error); + return error(); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { + static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) + return std::forward<_Up>(__error); + return std::move(error()); + } + + // [expected.void.monadic], monadic + template + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(value()) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), value()); + } + return _Up(unexpect, error()); + } + + template + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(value()) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), value()); + } + return _Up(unexpect, error()); + } + + template + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { + using _Up = remove_cvref_t>; + static_assert( + __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(value())) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), std::move(value())); + } + return _Up(unexpect, std::move(error())); + } + + template + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { + using _Up = remove_cvref_t>; + static_assert( + __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(value())) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), std::move(value())); + } + return _Up(unexpect, std::move(error())); + } + + template + requires is_constructible_v<_Tp, _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, value()); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template + requires is_constructible_v<_Tp, const _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, value()); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template + requires is_constructible_v<_Tp, _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { + using _Gp = remove_cvref_t>; + static_assert( + __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, std::move(value())); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template + requires is_constructible_v<_Tp, const _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { + using _Gp = remove_cvref_t>; + static_assert( + __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, std::move(value())); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); + } else { + std::invoke(std::forward<_Func>(__f), value()); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); + } else { + std::invoke(std::forward<_Func>(__f), value()); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>( + __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); + } else { + std::invoke(std::forward<_Func>(__f), std::move(value())); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>( + __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); + } else { + std::invoke(std::forward<_Func>(__f), std::move(value())); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Tp, _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, value()); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template + requires is_constructible_v<_Tp, const _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, value()); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template + requires is_constructible_v<_Tp, _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, std::move(value())); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + + template + requires is_constructible_v<_Tp, const _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, std::move(value())); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + // [expected.object.eq], equality operators template requires(!is_void_v<_T2>) @@ -625,24 +893,66 @@ public: private: struct __empty_t {}; - // use named union because [[no_unique_address]] cannot be applied to an unnamed union - _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { - _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + template + union __union_t { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) + requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} + + _ValueType __val_; + _ErrorType __unex_; + }; + + // use named union because [[no_unique_address]] cannot be applied to an unnamed union, + // also guaranteed elision into a potentially-overlapping subobject is unsettled (and + // it's not clear that it's implementable, given that the function is allowed to clobber + // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. + template + requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>) + union __union_t<_ValueType, _ErrorType> { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) + requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; - _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; - _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; - } __union_; + _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_; + _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; + }; + _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_; bool __has_val_; }; @@ -762,6 +1072,19 @@ public: std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); } +private: + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f) + : __has_val_(true) { + std::invoke(std::forward<_Func>(__f)); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} + +public: // [expected.void.dtor], destructor _LIBCPP_HIDE_FROM_ABI constexpr ~expected() @@ -894,41 +1217,270 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); } _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(__union_.__unex_); } } _LIBCPP_HIDE_FROM_ABI constexpr void value() && { if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); } } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } + template + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) { + return std::forward<_Up>(__error); + } + return error(); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { + static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) { + return std::forward<_Up>(__error); + } + return std::move(error()); + } + + // [expected.void.monadic], monadic + template + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, error()); + } + + template + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, error()); + } + + template + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, std::move(error())); + } + + template + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { + using _Up = remove_cvref_t>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, std::move(error())); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, + "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { + using _Gp = remove_cvref_t>; + static_assert(__is_std_expected<_Gp>::value, + "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { + using _Up = remove_cv_t>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { + using _Gp = remove_cv_t>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + // [expected.void.eq], equality operators template requires is_void_v<_T2> @@ -947,23 +1499,55 @@ public: private: struct __empty_t {}; - // use named union because [[no_unique_address]] cannot be applied to an unnamed union - _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { + + template + union __union_t { _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(is_trivially_destructible_v<_Err>) + requires(is_trivially_destructible_v<_ErrorType>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} + + __empty_t __empty_; + _ErrorType __unex_; + }; + + // use named union because [[no_unique_address]] cannot be applied to an unnamed union, + // also guaranteed elision into a potentially-overlapping subobject is unsettled (and + // it's not clear that it's implementable, given that the function is allowed to clobber + // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. + template + requires is_trivially_move_constructible_v<_ErrorType> + union __union_t<_ErrorType> { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(!is_trivially_destructible_v<_Err>) + requires(!is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; - _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; - } __union_; + _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; + }; + _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_; bool __has_val_; }; @@ -971,4 +1555,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_EXPECTED_H diff --git a/lib/libcxx/include/__expected/unexpect.h b/lib/libcxx/include/__expected/unexpect.h index 20bafc1107..df52787d36 100644 --- a/lib/libcxx/include/__expected/unexpect.h +++ b/lib/libcxx/include/__expected/unexpect.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct unexpect_t { - _LIBCPP_HIDE_FROM_ABI explicit unexpect_t() = default; + explicit unexpect_t() = default; }; inline constexpr unexpect_t unexpect{}; diff --git a/lib/libcxx/include/__expected/unexpected.h b/lib/libcxx/include/__expected/unexpected.h index 075963a84d..c7fe3c52e4 100644 --- a/lib/libcxx/include/__expected/unexpected.h +++ b/lib/libcxx/include/__expected/unexpected.h @@ -31,6 +31,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD @@ -119,4 +122,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_UNEXPECTED_H diff --git a/lib/libcxx/include/__filesystem/copy_options.h b/lib/libcxx/include/__filesystem/copy_options.h index 96c7535812..11962e494c 100644 --- a/lib/libcxx/include/__filesystem/copy_options.h +++ b/lib/libcxx/include/__filesystem/copy_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { none = 0, skip_existing = 1, @@ -75,8 +73,6 @@ inline copy_options& operator^=(copy_options& __lhs, copy_options __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/directory_entry.h b/lib/libcxx/include/__filesystem/directory_entry.h index b17eaaab4c..bb7a061db4 100644 --- a/lib/libcxx/include/__filesystem/directory_entry.h +++ b/lib/libcxx/include/__filesystem/directory_entry.h @@ -12,8 +12,8 @@ #include <__availability> #include <__chrono/time_point.h> +#include <__compare/ordering.h> #include <__config> -#include <__errc> #include <__filesystem/file_status.h> #include <__filesystem/file_time_type.h> #include <__filesystem/file_type.h> @@ -21,11 +21,12 @@ #include <__filesystem/operations.h> #include <__filesystem/path.h> #include <__filesystem/perms.h> +#include <__system_error/errc.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include <__utility/unreachable.h> #include -#include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,21 +35,20 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class directory_entry { typedef _VSTD_FS::path _Path; public: // constructors and destructors - directory_entry() noexcept = default; - directory_entry(directory_entry const&) = default; - directory_entry(directory_entry&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry() noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&) = default; + _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY explicit directory_entry(_Path const& __p) : __p_(__p) { @@ -61,10 +61,10 @@ public: __refresh(&__ec); } - ~directory_entry() {} + _LIBCPP_HIDE_FROM_ABI ~directory_entry() {} - directory_entry& operator=(directory_entry const&) = default; - directory_entry& operator=(directory_entry&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&) = default; + _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY void assign(_Path const& __p) { @@ -321,8 +321,7 @@ private: __data_ = __dt; } - _LIBCPP_FUNC_VIS - error_code __do_refresh() noexcept; + _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept; _LIBCPP_INLINE_VISIBILITY static bool __is_dne_error(error_code const& __ec) { @@ -510,17 +509,17 @@ public: private: friend class directory_iterator; friend class recursive_directory_iterator; - explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} - __dir_element_proxy(__dir_element_proxy&& __o) + _LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} + _LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(_VSTD::move(__o.__elem_)) {} directory_entry __elem_; }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__filesystem/directory_iterator.h b/lib/libcxx/include/__filesystem/directory_iterator.h index 5ff2f01ac7..632c2c8063 100644 --- a/lib/libcxx/include/__filesystem/directory_iterator.h +++ b/lib/libcxx/include/__filesystem/directory_iterator.h @@ -16,22 +16,24 @@ #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> #include <__filesystem/path.h> +#include <__iterator/default_sentinel.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class _LIBCPP_HIDDEN __dir_stream; class directory_iterator { @@ -81,7 +83,7 @@ public: _LIBCPP_HIDE_FROM_ABI const directory_entry& operator*() const { - _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); + _LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "The end iterator cannot be dereferenced"); return __dereference(); } @@ -101,21 +103,23 @@ public: _LIBCPP_HIDE_FROM_ABI directory_iterator& increment(error_code& __ec) { return __increment(&__ec); } +# if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept { return *this == directory_iterator(); } + +# endif + private: inline _LIBCPP_HIDE_FROM_ABI friend bool operator==(const directory_iterator& __lhs, const directory_iterator& __rhs) noexcept; // construct the dir_stream - _LIBCPP_FUNC_VIS - directory_iterator(const path&, error_code*, - directory_options = directory_options::none); + _LIBCPP_EXPORTED_FROM_ABI directory_iterator(const path&, error_code*, directory_options = directory_options::none); - _LIBCPP_FUNC_VIS - directory_iterator& __increment(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI directory_iterator& __increment(error_code* __ec = nullptr); - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; + _LIBCPP_EXPORTED_FROM_ABI const directory_entry& __dereference() const; private: shared_ptr<__dir_stream> __imp_; @@ -144,22 +148,22 @@ end(directory_iterator) noexcept { return directory_iterator(); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true; template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H diff --git a/lib/libcxx/include/__filesystem/directory_options.h b/lib/libcxx/include/__filesystem/directory_options.h index c5c031a567..4c323ccb0c 100644 --- a/lib/libcxx/include/__filesystem/directory_options.h +++ b/lib/libcxx/include/__filesystem/directory_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { none = 0, follow_directory_symlink = 1, @@ -73,8 +71,6 @@ inline directory_options& operator^=(directory_options& __lhs, return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/file_status.h b/lib/libcxx/include/__filesystem/file_status.h index ac3f6cbed9..0cf405b9c2 100644 --- a/lib/libcxx/include/__filesystem/file_status.h +++ b/lib/libcxx/include/__filesystem/file_status.h @@ -23,9 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -class _LIBCPP_TYPE_VIS file_status { +class _LIBCPP_EXPORTED_FROM_ABI file_status { public: // constructors _LIBCPP_INLINE_VISIBILITY @@ -35,14 +33,14 @@ public: : __ft_(__ft), __prms_(__prms) {} - file_status(const file_status&) noexcept = default; - file_status(file_status&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status(const file_status&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status(file_status&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY ~file_status() {} - file_status& operator=(const file_status&) noexcept = default; - file_status& operator=(file_status&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status& operator=(const file_status&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status& operator=(file_status&&) noexcept = default; // observers _LIBCPP_INLINE_VISIBILITY @@ -58,13 +56,19 @@ public: _LIBCPP_INLINE_VISIBILITY void permissions(perms __p) noexcept { __prms_ = __p; } +# if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const file_status& __lhs, const file_status& __rhs) noexcept { + return __lhs.type() == __rhs.type() && __lhs.permissions() == __rhs.permissions(); + } + +# endif + private: file_type __ft_; perms __prms_; }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/filesystem_error.h b/lib/libcxx/include/__filesystem/filesystem_error.h index effe699833..713cc357ee 100644 --- a/lib/libcxx/include/__filesystem/filesystem_error.h +++ b/lib/libcxx/include/__filesystem/filesystem_error.h @@ -14,11 +14,13 @@ #include <__config> #include <__filesystem/path.h> #include <__memory/shared_ptr.h> +#include <__system_error/error_code.h> +#include <__system_error/system_error.h> #include <__utility/forward.h> +#include <__verbose_abort> #include #include -#include -#include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,50 +30,38 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error { +class _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_EXPORTED_FROM_ABI filesystem_error : public system_error { public: - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(path(), path())) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(path(), path())) { __create_what(0); } - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, path())) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, const path& __p1, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(__p1, path())) { __create_what(1); } - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, const path& __p2, - error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, __p2)) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, const path& __p1, const path& __p2, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(__p1, __p2)) { __create_what(2); } - _LIBCPP_INLINE_VISIBILITY - const path& path1() const noexcept { return __storage_->__p1_; } + _LIBCPP_HIDE_FROM_ABI const path& path1() const noexcept { return __storage_->__p1_; } - _LIBCPP_INLINE_VISIBILITY - const path& path2() const noexcept { return __storage_->__p2_; } + _LIBCPP_HIDE_FROM_ABI const path& path2() const noexcept { return __storage_->__p2_; } - filesystem_error(const filesystem_error&) = default; + _LIBCPP_HIDE_FROM_ABI filesystem_error(const filesystem_error&) = default; ~filesystem_error() override; // key function _LIBCPP_HIDE_FROM_ABI_VIRTUAL - const char* what() const noexcept override { - return __storage_->__what_.c_str(); - } + const char* what() const noexcept override { return __storage_->__what_.c_str(); } void __create_what(int __num_paths); private: struct _LIBCPP_HIDDEN _Storage { - _LIBCPP_INLINE_VISIBILITY - _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} + _LIBCPP_HIDE_FROM_ABI _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} path __p1_; path __p2_; @@ -80,22 +70,19 @@ private: shared_ptr<_Storage> __storage_; }; -// TODO(ldionne): We need to pop the pragma and push it again after -// filesystem_error to work around PR41078. -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS template -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS -void __throw_filesystem_error(_Args&&... __args) { +_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY void +__throw_filesystem_error(_Args&&... __args) { throw filesystem_error(_VSTD::forward<_Args>(__args)...); } -#else -void __throw_filesystem_error(_Args&&...) { - _VSTD::abort(); +# else +template +_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY void +__throw_filesystem_error(_Args&&...) { + _LIBCPP_VERBOSE_ABORT("filesystem_error was thrown in -fno-exceptions mode"); } -#endif -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +# endif _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/lib/libcxx/include/__filesystem/operations.h b/lib/libcxx/include/__filesystem/operations.h index f48d301d09..71b3fb859d 100644 --- a/lib/libcxx/include/__filesystem/operations.h +++ b/lib/libcxx/include/__filesystem/operations.h @@ -21,46 +21,46 @@ #include <__filesystem/perm_options.h> #include <__filesystem/perms.h> #include <__filesystem/space_info.h> +#include <__system_error/error_code.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH -_LIBCPP_FUNC_VIS path __absolute(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __canonical(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __copy_file(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __copy(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __create_directories(const path&, error_code* = nullptr); -_LIBCPP_FUNC_VIS void __create_directory_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __create_directory(const path&, error_code* = nullptr); -_LIBCPP_FUNC_VIS bool __create_directory(const path&, const path& __attributes, error_code* = nullptr); -_LIBCPP_FUNC_VIS void __create_hard_link(const path& __to, const path& __new_hard_link, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __create_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __current_path(error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __current_path(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __equivalent(const path&, const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_status __status(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __file_size(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_status __symlink_status(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_time_type __last_write_time(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __last_write_time(const path&, file_time_type __new_time, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __weakly_canonical(path const& __p, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __read_symlink(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __remove_all(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __remove(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __rename(const path& __from, const path& __to, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __resize_file(const path&, uintmax_t __size, error_code* = nullptr); -_LIBCPP_FUNC_VIS path __temp_directory_path(error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __absolute(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __canonical(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __copy_file(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __copy(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directories(const path&, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_directory_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directory(const path&, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directory(const path&, const path& __attributes, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_hard_link(const path& __to, const path& __new_hard_link, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __current_path(error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __current_path(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __equivalent(const path&, const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_status __status(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __file_size(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_status __symlink_status(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_time_type __last_write_time(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __last_write_time(const path&, file_time_type __new_time, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __weakly_canonical(path const& __p, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __read_symlink(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __remove_all(const path&, error_code* __ec = nullptr); +_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); 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); } @@ -118,7 +118,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool is_character_file(const path& __p, error_code& inline _LIBCPP_HIDE_FROM_ABI bool is_directory(file_status __s) noexcept { return __s.type() == file_type::directory; } inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p) { return is_directory(__status(__p)); } inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p, error_code& __ec) noexcept { return is_directory(__status(__p, &__ec)); } -_LIBCPP_FUNC_VIS bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); +_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; } @@ -140,7 +140,7 @@ inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p) { r inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { return __last_write_time(__p, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t) { __last_write_time(__p, __t); } 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_FUNC_VIS void __permissions(const path&, perms, perm_options, error_code* = nullptr); +_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); } inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { __permissions(__p, __prms, perm_options::replace, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts, error_code& __ec) { __permissions(__p, __prms, __opts, &__ec); } @@ -180,7 +180,7 @@ inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to) { inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to, error_code& __ec) noexcept { return __rename(__from, __to, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns) { return __resize_file(__p, __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_FUNC_VIS space_info __space(const path&, error_code* __ec = nullptr); +_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); } inline _LIBCPP_HIDE_FROM_ABI file_status status(const path& __p) { return __status(__p); } @@ -192,10 +192,10 @@ inline _LIBCPP_HIDE_FROM_ABI path temp_directory_path(error_code& __ec) { return inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p) { return __weakly_canonical(__p); } inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p, error_code& __ec) { return __weakly_canonical(__p, &__ec); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_OPERATIONS_H diff --git a/lib/libcxx/include/__filesystem/path.h b/lib/libcxx/include/__filesystem/path.h index 4e6912fcf3..77699c5ae4 100644 --- a/lib/libcxx/include/__filesystem/path.h +++ b/lib/libcxx/include/__filesystem/path.h @@ -14,12 +14,18 @@ #include <__algorithm/replace_copy.h> #include <__availability> #include <__config> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__fwd/hash.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_pointer.h> #include #include #include -#include #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include // for quoted @@ -34,7 +40,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH template struct __can_convert_char { @@ -139,7 +145,7 @@ struct __is_pathable_string< } }; -template ::type, +template , class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >, bool _IsCharPtr = is_pointer<_DS>::value&& @@ -168,7 +174,7 @@ struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } }; -template ::value, +template ::value, class = void> struct __is_pathable_iter : false_type {}; @@ -217,10 +223,8 @@ typedef char __path_value; #endif #if defined(_LIBCPP_WIN32API) -_LIBCPP_FUNC_VIS -size_t __wide_to_char(const wstring&, char*, size_t); -_LIBCPP_FUNC_VIS -size_t __char_to_wide(const string&, wchar_t*, size_t); +_LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t); +_LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t); #endif template @@ -303,7 +307,7 @@ struct _PathCVT<__path_value> { template _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { for (; __b != __e; ++__b) __dest.push_back(*__b); @@ -311,7 +315,7 @@ struct _PathCVT<__path_value> { template _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { __dest.append(__b, __e); } @@ -348,7 +352,7 @@ struct _PathCVT { template _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { basic_string __tmp(__b, __e); __append_string(__dest, __tmp); @@ -356,7 +360,7 @@ struct _PathCVT { template _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { basic_string __tmp(__b, __e); __append_string(__dest, __tmp); @@ -439,7 +443,7 @@ struct _PathExport { #endif /* !_LIBCPP_HAS_NO_CHAR8_T */ #endif /* _LIBCPP_WIN32API */ -class _LIBCPP_TYPE_VIS path { +class _LIBCPP_EXPORTED_FROM_ABI path { template using _EnableIfPathable = typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; @@ -1029,7 +1033,7 @@ public: } // iterators - class _LIBCPP_TYPE_VIS iterator; + class _LIBCPP_EXPORTED_FROM_ABI iterator; typedef iterator const_iterator; iterator begin() const; @@ -1079,13 +1083,23 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } -_LIBCPP_FUNC_VIS -size_t hash_value(const path& __p) noexcept; +_LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM +_LIBCPP_BEGIN_NAMESPACE_STD + +template <> +struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<_VSTD_FS::path> : __unary_function<_VSTD_FS::path, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_VSTD_FS::path const& __p) const noexcept { + return _VSTD_FS::hash_value(__p); + } +}; + +_LIBCPP_END_NAMESPACE_STD + #endif // _LIBCPP_CXX03_LANG #endif // _LIBCPP___FILESYSTEM_PATH_H diff --git a/lib/libcxx/include/__filesystem/path_iterator.h b/lib/libcxx/include/__filesystem/path_iterator.h index 6f2baf8f7a..9961b46cf8 100644 --- a/lib/libcxx/include/__filesystem/path_iterator.h +++ b/lib/libcxx/include/__filesystem/path_iterator.h @@ -27,9 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -class _LIBCPP_TYPE_VIS path::iterator { +class _LIBCPP_EXPORTED_FROM_ABI path::iterator { public: enum _ParserState : unsigned char { _Singular, @@ -56,10 +54,10 @@ public: : __stashed_elem_(), __path_ptr_(nullptr), __entry_(), __state_(_Singular) {} - iterator(const iterator&) = default; - ~iterator() = default; + _LIBCPP_HIDE_FROM_ABI iterator(const iterator&) = default; + _LIBCPP_HIDE_FROM_ABI ~iterator() = default; - iterator& operator=(const iterator&) = default; + _LIBCPP_HIDE_FROM_ABI iterator& operator=(const iterator&) = default; _LIBCPP_INLINE_VISIBILITY reference operator*() const { return __stashed_elem_; } @@ -69,10 +67,10 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator++() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to increment a singular iterator"); - _LIBCPP_ASSERT(__state_ != _AtEnd, - "attempting to increment the end iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _Singular, + "attempting to increment a singular iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _AtEnd, + "attempting to increment the end iterator"); return __increment(); } @@ -85,10 +83,10 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator--() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to decrement a singular iterator"); - _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), - "attempting to decrement the begin iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _Singular, + "attempting to decrement a singular iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__entry_.data() != __path_ptr_->native().data(), + "attempting to decrement the begin iterator"); return __decrement(); } @@ -114,19 +112,19 @@ private: _ParserState __state_; }; +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs, const path::iterator& __rhs) { return __lhs.__path_ptr_ == __rhs.__path_ptr_ && __lhs.__entry_.data() == __rhs.__entry_.data(); } +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs, const path::iterator& __rhs) { return !(__lhs == __rhs); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/perm_options.h b/lib/libcxx/include/__filesystem/perm_options.h index 4aba302edf..e77af9ef97 100644 --- a/lib/libcxx/include/__filesystem/perm_options.h +++ b/lib/libcxx/include/__filesystem/perm_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { replace = 1, add = 2, @@ -68,8 +66,6 @@ inline perm_options& operator^=(perm_options& __lhs, perm_options __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/perms.h b/lib/libcxx/include/__filesystem/perms.h index df4590057e..77bc652103 100644 --- a/lib/libcxx/include/__filesystem/perms.h +++ b/lib/libcxx/include/__filesystem/perms.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - // On Windows, these permission bits map to one single readonly flag per // file, and the executable bit is always returned as set. When setting // permissions, as long as the write bit is set for either owner, group or @@ -86,8 +84,6 @@ inline perms& operator|=(perms& __lhs, perms __rhs) { return __lhs = __lhs | __r _LIBCPP_INLINE_VISIBILITY inline perms& operator^=(perms& __lhs, perms __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/recursive_directory_iterator.h b/lib/libcxx/include/__filesystem/recursive_directory_iterator.h index b20d201f58..c38d58e502 100644 --- a/lib/libcxx/include/__filesystem/recursive_directory_iterator.h +++ b/lib/libcxx/include/__filesystem/recursive_directory_iterator.h @@ -15,22 +15,24 @@ #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> #include <__filesystem/path.h> +#include <__iterator/default_sentinel.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class recursive_directory_iterator { public: @@ -59,10 +61,10 @@ public: recursive_directory_iterator(const path& __p, error_code& __ec) : recursive_directory_iterator(__p, directory_options::none, &__ec) {} - recursive_directory_iterator(const recursive_directory_iterator&) = default; - recursive_directory_iterator(recursive_directory_iterator&&) = default; + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator(const recursive_directory_iterator&) = default; + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator(recursive_directory_iterator&&) = default; - recursive_directory_iterator& + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator& operator=(const recursive_directory_iterator&) = default; _LIBCPP_INLINE_VISIBILITY @@ -76,7 +78,7 @@ public: return *this; } - ~recursive_directory_iterator() = default; + _LIBCPP_HIDE_FROM_ABI ~recursive_directory_iterator() = default; _LIBCPP_INLINE_VISIBILITY const directory_entry& operator*() const { return __dereference(); } @@ -84,7 +86,7 @@ public: _LIBCPP_INLINE_VISIBILITY const directory_entry* operator->() const { return &__dereference(); } - recursive_directory_iterator& operator++() { return __increment(); } + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator& operator++() { return __increment(); } _LIBCPP_INLINE_VISIBILITY __dir_element_proxy operator++(int) { @@ -98,8 +100,8 @@ public: return __increment(&__ec); } - _LIBCPP_FUNC_VIS directory_options options() const; - _LIBCPP_FUNC_VIS int depth() const; + _LIBCPP_EXPORTED_FROM_ABI directory_options options() const; + _LIBCPP_EXPORTED_FROM_ABI int depth() const; _LIBCPP_INLINE_VISIBILITY void pop() { __pop(); } @@ -113,25 +115,21 @@ public: _LIBCPP_INLINE_VISIBILITY void disable_recursion_pending() { __rec_ = false; } +# if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept { + return *this == recursive_directory_iterator(); + } + +# endif + private: - _LIBCPP_FUNC_VIS - recursive_directory_iterator(const path& __p, directory_options __opt, - error_code* __ec); - - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; - - _LIBCPP_FUNC_VIS - bool __try_recursion(error_code* __ec); - - _LIBCPP_FUNC_VIS - void __advance(error_code* __ec = nullptr); - - _LIBCPP_FUNC_VIS - recursive_directory_iterator& __increment(error_code* __ec = nullptr); - - _LIBCPP_FUNC_VIS - void __pop(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI recursive_directory_iterator(const path& __p, directory_options __opt, error_code* __ec); + _LIBCPP_EXPORTED_FROM_ABI const directory_entry& __dereference() const; + _LIBCPP_EXPORTED_FROM_ABI bool __try_recursion(error_code* __ec); + _LIBCPP_EXPORTED_FROM_ABI void __advance(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI recursive_directory_iterator& __increment(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI void __pop(error_code* __ec = nullptr); inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const recursive_directory_iterator&, @@ -164,22 +162,22 @@ end(recursive_directory_iterator) noexcept { return recursive_directory_iterator(); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true; template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H diff --git a/lib/libcxx/include/__filesystem/space_info.h b/lib/libcxx/include/__filesystem/space_info.h index d0747e35eb..929f514664 100644 --- a/lib/libcxx/include/__filesystem/space_info.h +++ b/lib/libcxx/include/__filesystem/space_info.h @@ -22,20 +22,16 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -struct _LIBCPP_TYPE_VIS space_info { +struct _LIBCPP_EXPORTED_FROM_ABI space_info { uintmax_t capacity; uintmax_t free; uintmax_t available; -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const space_info&, const space_info&) = default; # endif }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__filesystem/u8path.h b/lib/libcxx/include/__filesystem/u8path.h index d35faa14bb..90b879aec2 100644 --- a/lib/libcxx/include/__filesystem/u8path.h +++ b/lib/libcxx/include/__filesystem/u8path.h @@ -15,7 +15,6 @@ #include <__config> #include <__filesystem/path.h> #include -#include // Only required on Windows for __widen_from_utf8, and included conservatively // because it requires support for localization. @@ -31,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH template _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T @@ -99,7 +98,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T #endif } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/lib/libcxx/include/__format/buffer.h b/lib/libcxx/include/__format/buffer.h index ddfe76728e..45f9da8017 100644 --- a/lib/libcxx/include/__format/buffer.h +++ b/lib/libcxx/include/__format/buffer.h @@ -27,11 +27,18 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/wrap_iter.h> +#include <__memory/addressof.h> +#include <__memory/allocate_at_least.h> +#include <__memory/allocator_traits.h> +#include <__memory/construct_at.h> +#include <__memory/ranges_construct_at.h> +#include <__memory/uninitialized_algorithms.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/conditional.h> +#include <__utility/exception_guard.h> #include <__utility/move.h> #include #include -#include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -42,7 +49,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -100,7 +107,7 @@ public: size_t __n = __str.size(); __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::copy_n(__str.data(), __n, _VSTD::addressof(__ptr_[__size_])); __size_ += __n; return; @@ -108,7 +115,7 @@ public: // The output doesn't fit in the internal buffer. // Copy the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); const _InCharT* __first = __str.data(); do { size_t __chunk = _VSTD::min(__n, __capacity_); @@ -125,11 +132,11 @@ public: /// Like @ref __copy it may need to do type conversion. template <__fmt_char_type _InCharT, class _UnaryOperation> _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { - _LIBCPP_ASSERT(__first <= __last, "not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); size_t __n = static_cast(__last - __first); __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::transform(__first, __last, _VSTD::addressof(__ptr_[__size_]), _VSTD::move(__operation)); __size_ += __n; return; @@ -137,7 +144,7 @@ public: // The output doesn't fit in the internal buffer. // Transform the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { size_t __chunk = _VSTD::min(__n, __capacity_); _VSTD::transform(__first, __first + __chunk, _VSTD::addressof(__ptr_[__size_]), __operation); @@ -151,7 +158,7 @@ public: /// A \c fill_n wrapper. _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __n, __value); __size_ += __n; return; @@ -159,7 +166,7 @@ public: // The output doesn't fit in the internal buffer. // Fill the buffer in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { size_t __chunk = _VSTD::min(__n, __capacity_); _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __chunk, __value); @@ -246,9 +253,9 @@ class _LIBCPP_TEMPLATE_VIS __direct_storage {}; template concept __enable_direct_output = __fmt_char_type<_CharT> && (same_as<_OutIt, _CharT*> -#ifndef _LIBCPP_ENABLE_DEBUG_MODE + // TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an + // `#ifdef`. || same_as<_OutIt, __wrap_iter<_CharT*>> -#endif ); /// Write policy for directly writing to the underlying output. @@ -510,13 +517,19 @@ public: // context and the format arguments need to be retargeted to the new context. // This retargeting is done by a basic_format_context specialized for the // __iterator of this container. +// +// 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 { + using _Alloc = allocator<_CharT>; + public: using value_type = _CharT; struct __iterator { using difference_type = ptrdiff_t; + using value_type = _CharT; _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) : __buffer_(std::addressof(__buffer)) {} @@ -535,36 +548,101 @@ public: __retarget_buffer* __buffer_; }; - _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); } + __retarget_buffer(const __retarget_buffer&) = delete; + __retarget_buffer& operator=(const __retarget_buffer&) = delete; + + _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { + // When the initial size is very small a lot of resizes happen + // when elements added. So use a hard-coded minimum size. + // + // Note a size < 2 will not work + // - 0 there is no buffer, while push_back requires 1 empty element. + // - 1 multiplied by the grow factor is 1 and thus the buffer never + // grows. + auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT))); + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + + _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() { + ranges::destroy_n(__ptr_, __size_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + } _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } - _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); } + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + std::construct_at(__ptr_ + __size_, __c); + ++__size_; + + if (__size_ == __capacity_) + __grow_buffer(); + } template <__fmt_char_type _InCharT> _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { - __buffer_.insert(__buffer_.end(), __str.begin(), __str.end()); + size_t __n = __str.size(); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_); + __size_ += __n; } template <__fmt_char_type _InCharT, class _UnaryOperation> _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { - _LIBCPP_ASSERT(__first <= __last, "not a valid range"); - std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation)); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); + + size_t __n = static_cast(__last - __first); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_default_construct_n(__ptr_ + __size_, __n); + std::transform(__first, __last, __ptr_ + __size_, std::move(__operation)); + __size_ += __n; } - _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); } + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); - _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; } + std::uninitialized_fill_n(__ptr_ + __size_, __n, __value); + __size_ += __n; + } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; } private: - // Use vector instead of string to avoid adding zeros after every append - // operation. The buffer is exposed as a string_view and not as a c-string. - vector<_CharT> __buffer_; + _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); } + + _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { + _LIBCPP_ASSERT_UNCATEGORIZED(__capacity > __capacity_, "the buffer must grow"); + auto __result = std::__allocate_at_least(__alloc_, __capacity); + auto __guard = std::__make_exception_guard([&] { + allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count); + }); + // This shouldn't throw, but just to be safe. Note that at -O1 this + // 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_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; + _CharT* __ptr_; + size_t __capacity_; + size_t __size_{0}; }; } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/concepts.h b/lib/libcxx/include/__format/concepts.h index ba8d8e3162..ae96b6a198 100644 --- a/lib/libcxx/include/__format/concepts.h +++ b/lib/libcxx/include/__format/concepts.h @@ -16,9 +16,9 @@ #include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__type_traits/is_specialization.h> +#include <__type_traits/remove_const.h> #include <__utility/pair.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 /// The character type specializations of \ref formatter. template @@ -44,19 +44,23 @@ concept __fmt_char_type = template using __fmt_iter_for = _CharT*; -template -concept __formattable = - (semiregular, _CharT>>) && - requires(formatter, _CharT> __f, - const formatter, _CharT> __cf, - _Tp __t, - basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc, - basic_format_parse_context<_CharT> __pc) { - { __f.parse(__pc) } -> same_as::iterator>; - { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>; +template >> +concept __formattable_with = + semiregular<_Formatter> && + requires(_Formatter& __f, + const _Formatter& __cf, + _Tp&& __t, + _Context __fc, + basic_format_parse_context __pc) { + { __f.parse(__pc) } -> same_as; + { __cf.format(__t, __fc) } -> same_as; }; -# if _LIBCPP_STD_VER > 20 +template +concept __formattable = + __formattable_with, basic_format_context<__fmt_iter_for<_CharT>, _CharT>>; + +# if _LIBCPP_STD_VER >= 23 template concept formattable = __formattable<_Tp, _CharT>; @@ -69,8 +73,8 @@ template concept __fmt_pair_like = __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); -# endif //_LIBCPP_STD_VER > 20 -#endif //_LIBCPP_STD_VER > 17 +# endif //_LIBCPP_STD_VER >= 23 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/container_adaptor.h b/lib/libcxx/include/__format/container_adaptor.h index 62b698186e..ec806ef16b 100644 --- a/lib/libcxx/include/__format/container_adaptor.h +++ b/lib/libcxx/include/__format/container_adaptor.h @@ -14,17 +14,19 @@ # pragma GCC system_header #endif -#include <__availability> #include <__config> #include <__format/concepts.h> #include <__format/formatter.h> #include <__format/range_default_formatter.h> +#include <__ranges/ref_view.h> +#include <__type_traits/is_const.h> +#include <__type_traits/maybe_const.h> #include #include _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // [container.adaptors.format] only specifies the library should provide the // formatter specializations, not which header should provide them. @@ -33,10 +35,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD // adaptor headers. To use the format functions users already include . template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_container_adaptor { +struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { private: - using __maybe_const_adaptor = __fmt_maybe_const<_Adaptor, _CharT>; - formatter __underlying_; + using __maybe_const_container = __fmt_maybe_const; + using __maybe_const_adaptor = __maybe_const, _Adaptor>; + formatter, _CharT> __underlying_; public: template @@ -52,18 +55,18 @@ public: }; template _Container> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; template _Container> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_container_adaptor, _CharT> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/enable_insertable.h b/lib/libcxx/include/__format/enable_insertable.h index 71b4252930..86ef94a325 100644 --- a/lib/libcxx/include/__format/enable_insertable.h +++ b/lib/libcxx/include/__format/enable_insertable.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -28,7 +28,7 @@ inline constexpr bool __enable_insertable = false; } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/escaped_output_table.h b/lib/libcxx/include/__format/escaped_output_table.h index bd2994bdc6..222847e6af 100644 --- a/lib/libcxx/include/__format/escaped_output_table.h +++ b/lib/libcxx/include/__format/escaped_output_table.h @@ -72,7 +72,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 namespace __escaped_output_table { @@ -1031,7 +1031,7 @@ inline constexpr uint32_t __unallocated_region_lower_bound = 0x000323b0; } // namespace __escaped_output_table -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h index 1ffcfeb549..bd6d39fdc7 100644 --- a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -73,7 +73,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __extended_grapheme_custer_property_boundary { @@ -1654,7 +1654,7 @@ inline constexpr uint32_t __entries[1496] = { } // namespace __extended_grapheme_custer_property_boundary -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_arg.h b/lib/libcxx/include/__format/format_arg.h index 771a03ff2f..5cbfe81234 100644 --- a/lib/libcxx/include/__format/format_arg.h +++ b/lib/libcxx/include/__format/format_arg.h @@ -13,15 +13,17 @@ #include <__assert> #include <__concepts/arithmetic.h> #include <__config> -#include <__format/format_error.h> +#include <__format/concepts.h> #include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__functional/invoke.h> #include <__memory/addressof.h> +#include <__type_traits/conditional.h> #include <__utility/forward.h> +#include <__utility/move.h> #include <__utility/unreachable.h> #include <__variant/monostate.h> -#include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -30,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { /// The type stored in @ref basic_format_arg. @@ -81,7 +83,7 @@ constexpr bool __use_packed_format_arg_store(size_t __size) { return __size <= _ _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { - _LIBCPP_ASSERT(__id <= __packed_types_max, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__id <= __packed_types_max, ""); if (__id > 0) __types >>= __id * __packed_arg_t_bits; @@ -94,7 +96,7 @@ constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { // This function is not user obervable, so it can directly use the non-standard // types of the "variant". See __arg_t for more details. template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +_LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { case __format::__arg_t::__none: @@ -155,18 +157,14 @@ public: /// Contains the implementation for basic_format_arg::handle. struct __handle { template - _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp&& __v) noexcept + _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept : __ptr_(_VSTD::addressof(__v)), __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { - using _Dp = remove_cvref_t<_Tp>; - using _Formatter = typename _Context::template formatter_type<_Dp>; - constexpr bool __const_formattable = - requires { _Formatter().format(std::declval(), std::declval<_Context&>()); }; - using _Qp = conditional_t<__const_formattable, const _Dp, _Dp>; + using _Dp = remove_const_t<_Tp>; + using _Qp = conditional_t<__formattable_with, const _Dp, _Dp>; + static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10"); - static_assert(__const_formattable || !is_const_v>, "Mandated by [format.arg]/18"); - - _Formatter __f; + typename _Context::template formatter_type<_Dp> __f; __parse_ctx.advance_to(__f.parse(__parse_ctx)); __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast(__ptr)), __ctx)); }) {} @@ -218,13 +216,11 @@ public: _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept : __string_view_(__value) {} _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} - _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle __value) noexcept - // TODO FMT Investigate why it doesn't work without the forward. - : __handle_(std::forward<__handle>(__value)) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {} }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { +class _LIBCPP_TEMPLATE_VIS basic_format_arg { public: class _LIBCPP_TEMPLATE_VIS handle; @@ -276,7 +272,7 @@ private: // This function is user facing, so it must wrap the non-standard types of // the "variant" in a handle to stay conforming. See __arg_t for more details. template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +_LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { # ifndef _LIBCPP_HAS_NO_INT128 @@ -295,7 +291,7 @@ visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { } } -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_arg_store.h b/lib/libcxx/include/__format/format_arg_store.h index 6f4f4c3617..15ec8eb0a7 100644 --- a/lib/libcxx/include/__format/format_arg_store.h +++ b/lib/libcxx/include/__format/format_arg_store.h @@ -19,15 +19,15 @@ #include <__config> #include <__format/concepts.h> #include <__format/format_arg.h> -#include <__utility/forward.h> -#include +#include <__type_traits/conditional.h> +#include <__type_traits/extent.h> +#include <__type_traits/remove_const.h> #include #include -#include _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -142,21 +142,31 @@ consteval __arg_t __determine_arg_t() { // // Note this version can't be constrained avoiding ambiguous overloads. // That means it can be instantiated by disabled formatters. To solve this, a -// constrained version for not formattable formatters is added. That overload -// is marked as deleted to fail creating a storage type for disabled formatters. +// constrained version for not formattable formatters is added. template consteval __arg_t __determine_arg_t() { return __arg_t::__handle; } +// The overload for not formattable types allows triggering the static +// assertion below. template requires(!__formattable<_Tp, typename _Context::char_type>) -consteval __arg_t __determine_arg_t() = delete; +consteval __arg_t __determine_arg_t() { + return __arg_t::__none; +} +// Pseudo constuctor for basic_format_arg +// +// Modeled after template explicit basic_format_arg(T& v) noexcept; +// [format.arg]/4-6 template -_LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __value) noexcept { - constexpr __arg_t __arg = __determine_arg_t<_Context, remove_cvref_t<_Tp>>(); - static_assert(__arg != __arg_t::__none); +_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>(); + static_assert(__arg != __arg_t::__none, "the supplied type is not formattable"); + + static_assert(__formattable_with<_Tp, _Context>); // Not all types can be used to directly initialize the // __basic_format_arg_value. First handle all types needing adjustment, the @@ -175,9 +185,9 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __val 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>) + if constexpr (is_array_v<_Dp>) return basic_format_arg<_Context>{ - __arg, basic_string_view{__value, extent_v> - 1}}; + __arg, basic_string_view{__value, extent_v<_Dp> - 1}}; else // When the _Traits or _Allocator are different an implicit conversion will // fail. @@ -186,8 +196,7 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __val else if constexpr (__arg == __arg_t::__ptr) return basic_format_arg<_Context>{__arg, static_cast(__value)}; else if constexpr (__arg == __arg_t::__handle) - return basic_format_arg<_Context>{ - __arg, typename __basic_format_arg_value<_Context>::__handle{_VSTD::forward<_Tp>(__value)}}; + return basic_format_arg<_Context>{__arg, typename __basic_format_arg_value<_Context>::__handle{__value}}; else return basic_format_arg<_Context>{__arg, __value}; } @@ -218,7 +227,7 @@ _LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* template struct __packed_format_arg_store { __basic_format_arg_value<_Context> __values_[N]; - uint64_t __types_; + uint64_t __types_ = 0; }; template @@ -247,7 +256,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { _Storage __storage; }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_args.h b/lib/libcxx/include/__format/format_args.h index 8b8fbde92f..defb42a4ab 100644 --- a/lib/libcxx/include/__format/format_args.h +++ b/lib/libcxx/include/__format/format_args.h @@ -24,12 +24,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args { +class _LIBCPP_TEMPLATE_VIS basic_format_args { public: - _LIBCPP_HIDE_FROM_ABI basic_format_args() noexcept = default; + basic_format_args() noexcept = default; template _LIBCPP_HIDE_FROM_ABI basic_format_args(const __format_arg_store<_Context, _Args...>& __store) noexcept @@ -71,9 +71,11 @@ private: const basic_format_arg<_Context>* __args_; }; }; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_args); -#endif //_LIBCPP_STD_VER > 17 +template +basic_format_args(__format_arg_store<_Context, _Args...>) -> basic_format_args<_Context>; + +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_context.h b/lib/libcxx/include/__format/format_context.h index 85e00eb222..9d50cee248 100644 --- a/lib/libcxx/include/__format/format_context.h +++ b/lib/libcxx/include/__format/format_context.h @@ -37,11 +37,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; +class _LIBCPP_TEMPLATE_VIS basic_format_context; #ifndef _LIBCPP_HAS_NO_LOCALIZATION /** @@ -80,7 +80,6 @@ requires output_iterator<_OutIt, const _CharT&> class // clang-format off _LIBCPP_TEMPLATE_VIS - _LIBCPP_AVAILABILITY_FORMAT _LIBCPP_PREFERRED_NAME(format_context) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) // clang-format on @@ -121,9 +120,9 @@ private: // TODO FMT Validate whether lazy creation is the best solution. optional<_VSTD::locale> __loc_; - template - friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> - __format_context_create(__OutIt, basic_format_args>, + template + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT> + __format_context_create(_OtherOutIt, basic_format_args>, optional<_VSTD::locale>&&); // Note: the Standard doesn't specify the required constructors. @@ -134,9 +133,9 @@ private: : __out_it_(_VSTD::move(__out_it)), __args_(__args), __loc_(_VSTD::move(__loc)) {} #else - template - friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> - __format_context_create(__OutIt, basic_format_args>); + template + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT> + __format_context_create(_OtherOutIt, basic_format_args>); _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(_OutIt __out_it, @@ -162,7 +161,7 @@ private: // 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 _LIBCPP_AVAILABILITY_FORMAT +class _LIBCPP_TEMPLATE_VIS basic_format_context::__iterator, _CharT> { public: using iterator = typename __format::__retarget_buffer<_CharT>::__iterator; @@ -216,7 +215,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_error.h b/lib/libcxx/include/__format/format_error.h index 002d1a40a2..f22cb0b81e 100644 --- a/lib/libcxx/include/__format/format_error.h +++ b/lib/libcxx/include/__format/format_error.h @@ -11,7 +11,7 @@ #define _LIBCPP___FORMAT_FORMAT_ERROR_H #include <__config> -#include +#include <__verbose_abort> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,35 +20,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error { +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") +class _LIBCPP_EXPORTED_FROM_ABI format_error : public runtime_error { public: _LIBCPP_HIDE_FROM_ABI explicit format_error(const string& __s) : runtime_error(__s) {} _LIBCPP_HIDE_FROM_ABI explicit format_error(const char* __s) : runtime_error(__s) {} - // TODO FMT Remove when format is no longer experimental. - // Avoids linker errors when building the Clang-cl Windows DLL which doesn't - // support the experimental library. -# ifndef _LIBCPP_INLINE_FORMAT_ERROR_DTOR - ~format_error() noexcept override; -# else - ~format_error() noexcept override {} -# endif + _LIBCPP_HIDE_FROM_ABI_VIRTUAL + ~format_error() noexcept override = default; }; +_LIBCPP_DIAGNOSTIC_POP _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_format_error(const char* __s) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw format_error(__s); #else - (void)__s; - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("format_error was thrown in -fno-exceptions mode with message \"%s\"", __s); #endif } -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_functions.h b/lib/libcxx/include/__format/format_functions.h index 0f0001272d..27ec0a295f 100644 --- a/lib/libcxx/include/__format/format_functions.h +++ b/lib/libcxx/include/__format/format_functions.h @@ -10,16 +10,10 @@ #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS -// TODO FMT This is added to fix Apple back-deployment. -#include -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #include <__algorithm/clamp.h> -#include <__availability> #include <__concepts/convertible_to.h> #include <__concepts/same_as.h> #include <__config> -#include <__debug> #include <__format/buffer.h> #include <__format/format_arg.h> #include <__format/format_arg_store.h> @@ -38,7 +32,9 @@ #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> // iter_value_t #include <__variant/monostate.h> #include #include @@ -54,7 +50,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // TODO FMT Evaluate which templates should be external templates. This // improves the efficiency of the header. However since the header is still @@ -67,16 +63,17 @@ using wformat_args = basic_format_args; #endif template -_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { return _VSTD::__format_arg_store<_Context, _Args...>(__args...); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store +make_wformat_args(_Args&&... __args) { return _VSTD::__format_arg_store(__args...); } -#endif +# endif namespace __format { @@ -87,14 +84,16 @@ namespace __format { template class _LIBCPP_TEMPLATE_VIS __compile_time_handle { public: - _LIBCPP_HIDE_FROM_ABI - constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } + template + _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const { + __parse_(__ctx); + } template _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { - __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { + __parse_ = [](basic_format_parse_context<_CharT>& __ctx) { formatter<_Tp, _CharT> __f; - __parse_ctx.advance_to(__f.parse(__parse_ctx)); + __ctx.advance_to(__f.parse(__ctx)); }; } @@ -128,13 +127,13 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { if (__id >= __size_) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); return __args_[__id]; } _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { if (__id >= __size_) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); return __handles_[__id]; } @@ -147,41 +146,44 @@ private: size_t __size_; }; -_LIBCPP_HIDE_FROM_ABI -constexpr void __compile_time_validate_integral(__arg_t __type) { - switch (__type) { - case __arg_t::__int: - case __arg_t::__long_long: - case __arg_t::__i128: - case __arg_t::__unsigned: - case __arg_t::__unsigned_long_long: - case __arg_t::__u128: - return; - - default: - std::__throw_format_error("Argument isn't an integral type"); - } -} - +// [format.string.std]/8 +// If { arg-idopt } is used in a width or precision, the value of the +// corresponding formatting argument is used in its place. If the +// corresponding formatting argument is not of standard signed or unsigned +// integer type, or its value is negative for precision or non-positive for +// width, an exception of type format_error is thrown. +// // _HasPrecision does the formatter have a precision? template -_LIBCPP_HIDE_FROM_ABI constexpr void -__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, - __compile_time_basic_format_context<_CharT>& __ctx) { +_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument( + basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) { + auto __validate_type = [](__arg_t __type) { + // LWG3720 originally allowed "signed or unsigned integer types", however + // the final version explicitly changed it to "*standard* signed or unsigned + // integer types". It's trivial to use 128-bit integrals in libc++'s + // implementation, but other implementations may not implement it. + // (Using a width or precision, that does not fit in 64-bits, sounds very + // unlikely in real world code.) + switch (__type) { + case __arg_t::__int: + case __arg_t::__long_long: + case __arg_t::__unsigned: + case __arg_t::__unsigned_long_long: + return; + + default: + std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); + } + }; + formatter<_Tp, _CharT> __formatter; __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); - // [format.string.std]/7 - // ... If the corresponding formatting argument is not of integral type, or - // its value is negative for precision or non-positive for width, an - // exception of type format_error is thrown. - // - // Validate whether the arguments are integrals. if (__formatter.__parser_.__width_as_arg_) - __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); + __validate_type(__ctx.arg(__formatter.__parser_.__width_)); if constexpr (_HasPrecision) if (__formatter.__parser_.__precision_as_arg_) - __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); + __validate_type(__ctx.arg(__formatter.__parser_.__precision_)); } // This function is not user facing, so it can directly use the non-standard types of the "variant". @@ -236,30 +238,31 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma std::__throw_format_error("Invalid argument"); } -template -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__handle_replacement_field(const _CharT* __begin, const _CharT* __end, +template +_LIBCPP_HIDE_FROM_ABI constexpr _Iterator +__handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { + using _CharT = iter_value_t<_Iterator>; __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); - bool __parse = *__r.__ptr == _CharT(':'); - switch (*__r.__ptr) { + bool __parse = *__r.__last == _CharT(':'); + switch (*__r.__last) { case _CharT(':'): // The arg-id has a format-specifier, advance the input to the format-spec. - __parse_ctx.advance_to(__r.__ptr + 1); + __parse_ctx.advance_to(__r.__last + 1); break; case _CharT('}'): // The arg-id has no format-specifier. - __parse_ctx.advance_to(__r.__ptr); + __parse_ctx.advance_to(__r.__last); break; default: - std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'"); + std::__throw_format_error("The argument index should end with a ':' or a '}'"); } if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { __arg_t __type = __ctx.arg(__r.__value); if (__type == __arg_t::__none) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); else if (__type == __arg_t::__handle) __ctx.__handle(__r.__value).__parse(__parse_ctx); else if (__parse) @@ -268,7 +271,7 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end, _VSTD::__visit_format_arg( [&](auto __arg) { if constexpr (same_as) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); else if constexpr (same_as::handle>) __arg.format(__parse_ctx, __ctx); else { @@ -293,8 +296,8 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { using _CharT = typename _ParseCtx::char_type; static_assert(same_as); - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); typename _Ctx::iterator __out_it = __ctx.out(); while (__begin != __end) { switch (*__begin) { @@ -341,7 +344,7 @@ struct _LIBCPP_TEMPLATE_VIS basic_format_string { _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; } @@ -353,20 +356,6 @@ private: static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; - // TODO FMT remove this work-around when the AIX ICE has been resolved. -# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 - template - static constexpr __format::__compile_time_handle<_CharT> __get_handle() { - __format::__compile_time_handle<_CharT> __handle; - if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) - __handle.template __enable<_Tp>(); - - return __handle; - } - - static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ - __get_handle<_Args>()...}; -# else static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { using _Tp = remove_cvref_t<_Args>; __format::__compile_time_handle<_CharT> __handle; @@ -375,7 +364,6 @@ private: return __handle; }()...}; -# endif }; template @@ -406,21 +394,21 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt // https://reviews.llvm.org/D110499#inline-1180704 // TODO FMT Evaluate whether we want to file a Clang bug report regarding this. template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); } #endif template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_format_args(__args...)); @@ -428,42 +416,48 @@ format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +// 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 +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { string __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); return __res; } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// 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 +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { wstring __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); return __res; } -#endif +# endif template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, - _Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +format(format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); } -#endif +# endif template _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, @@ -476,14 +470,14 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, } template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); @@ -499,20 +493,20 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, } template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } -#endif +# endif -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# ifndef _LIBCPP_HAS_NO_LOCALIZATION template requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt @@ -533,7 +527,7 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt } template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to( _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, __args); @@ -541,7 +535,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to( _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, __args); @@ -549,7 +543,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v #endif template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); @@ -557,14 +551,17 @@ format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&. #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +// 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 +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { string __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, @@ -572,32 +569,34 @@ vformat(locale __loc, string_view __fmt, format_args __args) { return __res; } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// 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 +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { wstring __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, __args); return __res; } -#endif +# endif template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - format_string<_Args...> __fmt, - _Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } -#endif +# endif template _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, @@ -611,7 +610,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, } template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), @@ -620,7 +619,7 @@ format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), @@ -638,26 +637,23 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ } template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } -#endif +# endif -#endif // _LIBCPP_HAS_NO_LOCALIZATION +# endif // _LIBCPP_HAS_NO_LOCALIZATION - -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS diff --git a/lib/libcxx/include/__format/format_fwd.h b/lib/libcxx/include/__format/format_fwd.h index f7c72e2121..120b2fc8d4 100644 --- a/lib/libcxx/include/__format/format_fwd.h +++ b/lib/libcxx/include/__format/format_fwd.h @@ -20,19 +20,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg; +class _LIBCPP_TEMPLATE_VIS basic_format_arg; template requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; +class _LIBCPP_TEMPLATE_VIS basic_format_context; template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter; +struct _LIBCPP_TEMPLATE_VIS formatter; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_parse_context.h b/lib/libcxx/include/__format/format_parse_context.h index 30e3a7dfda..79f53f77d4 100644 --- a/lib/libcxx/include/__format/format_parse_context.h +++ b/lib/libcxx/include/__format/format_parse_context.h @@ -12,6 +12,7 @@ #include <__config> #include <__format/format_error.h> +#include <__type_traits/is_constant_evaluated.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,10 +21,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { +class _LIBCPP_TEMPLATE_VIS basic_format_parse_context { public: using char_type = _CharT; using const_iterator = typename basic_string_view<_CharT>::const_iterator; @@ -58,6 +59,18 @@ public: if (__indexing_ == __unknown) __indexing_ = __automatic; + + // Throws an exception to make the expression a non core constant + // expression as required by: + // [format.parse.ctx]/8 + // Remarks: Let cur-arg-id be the value of next_arg_id_ prior to this + // call. Call expressions where cur-arg-id >= num_args_ is true are not + // core constant expressions (7.7 [expr.const]). + // Note: the Throws clause [format.parse.ctx]/9 doesn't specify the + // behavior when id >= num_args_. + if (is_constant_evaluated() && __next_arg_id_ >= __num_args_) + std::__throw_format_error("Argument index outside the valid range"); + return __next_arg_id_++; } _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { @@ -93,7 +106,7 @@ using format_parse_context = basic_format_parse_context; using wformat_parse_context = basic_format_parse_context; #endif -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_string.h b/lib/libcxx/include/__format/format_string.h index d9caf866a1..2e1c71b3d0 100644 --- a/lib/libcxx/include/__format/format_string.h +++ b/lib/libcxx/include/__format/format_string.h @@ -13,6 +13,8 @@ #include <__assert> #include <__config> #include <__format/format_error.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t #include #include @@ -22,22 +24,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { -template +template struct _LIBCPP_TEMPLATE_VIS __parse_number_result { - const _CharT* __ptr; + _Iterator __last; uint32_t __value; }; -template -__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>; +template +__parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>; -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end); /** * The maximum value of a numeric argument. @@ -53,27 +55,28 @@ __parse_number(const _CharT* __begin, const _CharT* __end); inline constexpr uint32_t __number_max = INT32_MAX; namespace __detail { -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) { __parse_ctx.check_arg_id(0); return {++__begin, 0}; // can never be larger than the maximum. } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) { size_t __value = __parse_ctx.next_arg_id(); - _LIBCPP_ASSERT(__value <= __number_max, - "Compilers don't support this number of arguments"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __value <= __number_max, + "Compilers don't support this number of arguments"); return {__begin, uint32_t(__value)}; } -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { - __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end); +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end); __parse_ctx.check_arg_id(__r.__value); return __r; } @@ -86,9 +89,10 @@ __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { * The number is used for the 31-bit values @em width and @em precision. This * allows a maximum value of 2147483647. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end_input) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end_input) { + using _CharT = iter_value_t<_Iterator>; static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value."); /* @@ -98,7 +102,7 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { * - Does the value exceed width of an uint32_t? (Switching to uint64_t would * have the same issue, but with a higher maximum.) */ - const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; + _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; uint32_t __value = *__begin - _CharT('0'); while (++__begin != __end) { if (*__begin < _CharT('0') || *__begin > _CharT('9')) @@ -120,7 +124,7 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9'))) - std::__throw_format_error("The numeric value of the format-spec is too large"); + std::__throw_format_error("The numeric value of the format specifier is too large"); __value = __v; } @@ -134,9 +138,10 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { * The parser will return a pointer beyond the last consumed character. This * should be the closing '}' of the arg-id. */ -template -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; switch (*__begin) { case _CharT('0'): return __detail::__parse_zero(__begin, __end, __parse_ctx); @@ -149,14 +154,14 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { return __detail::__parse_automatic(__begin, __end, __parse_ctx); } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - std::__throw_format_error("The arg-id of the format-spec starts with an invalid character"); + std::__throw_format_error("The argument index starts with an invalid character"); return __detail::__parse_manual(__begin, __end, __parse_ctx); } } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_to_n_result.h b/lib/libcxx/include/__format/format_to_n_result.h index f1ed9a0982..6f30546dec 100644 --- a/lib/libcxx/include/__format/format_to_n_result.h +++ b/lib/libcxx/include/__format/format_to_n_result.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct _LIBCPP_TEMPLATE_VIS format_to_n_result { @@ -28,7 +28,7 @@ struct _LIBCPP_TEMPLATE_VIS format_to_n_result { }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(format_to_n_result); -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter.h b/lib/libcxx/include/__format/formatter.h index 900a09af4e..172b2d5f7b 100644 --- a/lib/libcxx/include/__format/formatter.h +++ b/lib/libcxx/include/__format/formatter.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 /// The default formatter template. /// @@ -32,13 +32,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD /// - is_copy_assignable, and /// - is_move_assignable. template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { +struct _LIBCPP_TEMPLATE_VIS formatter { formatter() = delete; formatter(const formatter&) = delete; formatter& operator=(const formatter&) = delete; }; -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template _LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { @@ -46,8 +46,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { __formatter.set_debug_format(); } -# endif // _LIBCPP_STD_VER > 20 -#endif // _LIBCPP_STD_VER > 17 +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_bool.h b/lib/libcxx/include/__format/formatter_bool.h index 0d005a1bee..3c8ae95f55 100644 --- a/lib/libcxx/include/__format/formatter_bool.h +++ b/lib/libcxx/include/__format/formatter_bool.h @@ -11,17 +11,15 @@ #define _LIBCPP___FORMAT_FORMATTER_BOOL_H #include <__algorithm/copy.h> +#include <__assert> #include <__availability> #include <__config> -#include <__debug> #include <__format/concepts.h> -#include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> #include <__format/formatter_integral.h> #include <__format/parser_std_format_spec.h> #include <__utility/unreachable.h> -#include #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include @@ -33,19 +31,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { +struct _LIBCPP_TEMPLATE_VIS formatter { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_bool(__parser_); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_bool(__parser_, "a bool"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(bool __value, _FormatContext& __ctx) const { switch (__parser_.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__string: @@ -63,7 +62,7 @@ public: static_cast(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx)); default: - _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parse function should have validated the type"); __libcpp_unreachable(); } } @@ -71,7 +70,7 @@ public: __format_spec::__parser<_CharT> __parser_; }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_char.h b/lib/libcxx/include/__format/formatter_char.h index 8a92e7445b..d6e61e8654 100644 --- a/lib/libcxx/include/__format/formatter_char.h +++ b/lib/libcxx/include/__format/formatter_char.h @@ -19,6 +19,7 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__format/write_escaped.h> #include <__type_traits/conditional.h> #include <__type_traits/is_signed.h> @@ -28,23 +29,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_char { +struct _LIBCPP_TEMPLATE_VIS __formatter_char { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_char(__parser_); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_char(__parser_, "a character"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(_CharT __value, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT __value, _FormatContext& __ctx) const { if (__parser_.__type_ == __format_spec::__type::__default || __parser_.__type_ == __format_spec::__type::__char) return __formatter::__format_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 if (__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); # endif @@ -60,13 +62,14 @@ public: return __formatter::__format_integer(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); } - _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) const -> decltype(__ctx.out()) + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(char __value, _FormatContext& __ctx) const requires(same_as<_CharT, wchar_t>) { return format(static_cast(__value), __ctx); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } # endif @@ -74,19 +77,19 @@ public: }; template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char {}; +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char {}; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char {}; +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char {}; template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_char { +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_char { }; # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_floating_point.h b/lib/libcxx/include/__format/formatter_floating_point.h index ca065723e1..fbb8aa9200 100644 --- a/lib/libcxx/include/__format/formatter_floating_point.h +++ b/lib/libcxx/include/__format/formatter_floating_point.h @@ -16,6 +16,9 @@ #include <__algorithm/min.h> #include <__algorithm/rotate.h> #include <__algorithm/transform.h> +#include <__charconv/chars_format.h> +#include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_result.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> @@ -25,10 +28,14 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__iterator/concepts.h> #include <__memory/allocator.h> +#include <__system_error/errc.h> +#include <__type_traits/conditional.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include +#include +#include #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include @@ -43,28 +50,28 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { template _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } template _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } template _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt, __precision); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } @@ -246,10 +253,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffe __result.__radix_point = __result.__last; // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last || *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; @@ -299,10 +306,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(cons } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent != __result.__last && *__result.__exponent == 'p'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'p'), + "Post-condition failure."); // clang-format on return __result; @@ -329,7 +336,7 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision); char* __first = __integral + 1; - _LIBCPP_ASSERT(__first != __result.__last, "No exponent present"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __result.__last, "No exponent present"); if (*__first == '.') { __result.__radix_point = __first; __result.__exponent = __formatter::__find_exponent(__first + 1, __result.__last); @@ -339,10 +346,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent != __result.__last && *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; } @@ -372,10 +379,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer< __result.__exponent = __result.__last; // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last), + "Post-condition failure."); // clang-format on return __result; } @@ -409,10 +416,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_ } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last || *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; @@ -484,7 +491,7 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer( return __formatter::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first); default: - _LIBCPP_ASSERT(false, "The parser should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parser should have validated the type"); __libcpp_unreachable(); } } @@ -522,7 +529,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( if (__size < __specs.__width_) { if (__zero_padding) { __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); } __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); @@ -602,10 +609,40 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_floating_point_non_finite( return __formatter::__write(__buffer, __last, _VSTD::move(__out_it), __specs); } -template -_LIBCPP_HIDE_FROM_ABI auto -__format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +/// Writes additional zero's for the precision before the exponent. +/// This is used when the precision requested in the format string is larger +/// than the maximum precision of the floating-point type. These precision +/// digits are always 0. +/// +/// \param __exponent The location of the exponent character. +/// \param __num_trailing_zeros The number of 0's to write before the exponent +/// character. +template +_LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( + const _CharT* __first, + const _CharT* __last, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + size_t __size, + const _CharT* __exponent, + size_t __num_trailing_zeros) -> decltype(__out_it) { + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__num_trailing_zeros > 0, + "The overload not writing trailing zeros should have been used"); + + __padding_size_result __padding = + __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); + __out_it = __formatter::__copy(__exponent, __last, _VSTD::move(__out_it)); + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + + +template +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_floating_point(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { bool __negative = _VSTD::signbit(__value); if (!_VSTD::isfinite(__value)) [[unlikely]] @@ -707,7 +744,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif // After the sign is written, zero padding is the same a right alignment // with '0'. __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); } if (__num_trailing_zeros) @@ -722,15 +759,15 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_floating_point { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_floating_point); - __format_spec::__process_parsed_floating_point(__parser_); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_floating_point); + __format_spec::__process_parsed_floating_point(__parser_, "a floating-point"); return __result; } - template - _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Tp __value, _FormatContext& __ctx) const { return __formatter::__format_floating_point(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); } @@ -738,16 +775,16 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_floating_point<_CharT> {}; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_integer.h b/lib/libcxx/include/__format/formatter_integer.h index b4be9f9a07..5590bff5aa 100644 --- a/lib/libcxx/include/__format/formatter_integer.h +++ b/lib/libcxx/include/__format/formatter_integer.h @@ -19,8 +19,8 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__type_traits/is_void.h> #include <__type_traits/make_32_64_or_128_bit.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,28 +28,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> - struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_integer { + struct _LIBCPP_TEMPLATE_VIS __formatter_integer { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_integer(__parser_); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_integer(__parser_, "an integer"); return __result; } - template - _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Tp __value, _FormatContext& __ctx) const { __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); if (__specs.__std_.__type_ == __format_spec::__type::__char) return __formatter::__format_char(__value, __ctx.out(), __specs); using _Type = __make_32_64_or_128_bit_t<_Tp>; - static_assert(!is_same<_Type, void>::value, "unsupported integral type used in __formatter_integer::__format"); + static_assert(!is_void<_Type>::value, "unsupported integral type used in __formatter_integer::__format"); // Reduce the number of instantiation of the integer formatter return __formatter::__format_integer(static_cast<_Type>(__value), __ctx, __specs); @@ -60,47 +60,47 @@ public: // Signed integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> { }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_integer<_CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; # ifndef _LIBCPP_HAS_NO_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__int128_t, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif // Unsigned integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_integer<_CharT> {}; # ifndef _LIBCPP_HAS_NO_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__uint128_t, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_integral.h b/lib/libcxx/include/__format/formatter_integral.h index fe3a06311b..54246aa027 100644 --- a/lib/libcxx/include/__format/formatter_integral.h +++ b/lib/libcxx/include/__format/formatter_integral.h @@ -10,6 +10,9 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H #define _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H +#include <__charconv/to_chars_integral.h> +#include <__charconv/to_chars_result.h> +#include <__charconv/traits.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> @@ -17,11 +20,13 @@ #include <__format/format_error.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__system_error/errc.h> +#include <__type_traits/make_unsigned.h> #include <__utility/unreachable.h> #include -#include #include #include +#include #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include @@ -36,7 +41,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -80,9 +85,9 @@ _LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, _ * regardless whether the @c std::numpunct's type is @c char or @c wchar_t. */ _LIBCPP_HIDE_FROM_ABI inline string __determine_grouping(ptrdiff_t __size, const string& __grouping) { - _LIBCPP_ASSERT(!__grouping.empty() && __size > __grouping[0], - "The slow grouping formatting is used while there will be no " - "separators written"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__grouping.empty() && __size > __grouping[0], + "The slow grouping formatting is used while there will be no " + "separators written"); string __r; auto __end = __grouping.end() - 1; auto __ptr = __grouping.begin(); @@ -149,7 +154,7 @@ _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value // TODO FMT Evaluate code overhead due to not calling the internal function // directly. (Should be zero overhead.) to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __base); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } @@ -198,16 +203,82 @@ consteval size_t __buffer_size() noexcept + 1; // Reserve space for the sign. } -template -_LIBCPP_HIDE_FROM_ABI auto __format_integer( +template +_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first, + const char* __last, string&& __grouping, _CharT __sep, + __format_spec::__parsed_specifications<_CharT> __specs) { + int __size = (__first - __begin) + // [sign][prefix] + (__last - __first) + // data + (__grouping.size() - 1); // number of separator characters + + __padding_size_result __padding = {0, 0}; + if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) { + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + + if (__specs.__width_ > __size) { + // Write zero padding. + __padding.__before_ = __specs.__width_ - __size; + __out_it = __formatter::__fill(_VSTD::move(__out_it), __specs.__width_ - __size, _CharT('0')); + } + } else { + if (__specs.__width_ > __size) { + // Determine padding and write padding. + __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); + + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + } + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + } + + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + _LIBCPP_ASSERT_UNCATEGORIZED(__r != __e, "The slow grouping formatting is used while " + "there will be no separators written."); + // The output is divided in small groups of numbers to write: + // - A group before the first separator. + // - A separator and a group, repeated for the number of separators. + // - A group after the last separator. + // This loop achieves that process by testing the termination condition + // midway in the loop. + // + // TODO FMT This loop evaluates the loop invariant `__parser.__type != + // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test + // happens in the __write call.) Benchmark whether making two loops and + // hoisting the invariant is worth the effort. + while (true) { + if (__specs.__std_.__type_ == __format_spec::__type::__hexadecimal_upper_case) { + __last = __first + *__r; + __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __hex_to_upper); + __first = __last; + } else { + __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + } + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + + + +template +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_integer( _Tp __value, - auto& __ctx, + _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative, char* __begin, char* __end, const char* __prefix, - int __base) -> decltype(__ctx.out()) { + int __base) { char* __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_); if (__specs.__std_.__alternate_form_ && __prefix) while (*__prefix) @@ -246,7 +317,7 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( // - Write data right aligned with '0' as fill character. __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); int32_t __size = __first - __begin; __specs.__width_ -= _VSTD::min(__size, __specs.__width_); @@ -258,10 +329,12 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, __formatter::__hex_to_upper); } -template -_LIBCPP_HIDE_FROM_ABI auto __format_integer( - _Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative = false) - -> decltype(__ctx.out()) { +template +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_integer(_Tp __value, + _FormatContext& __ctx, + __format_spec::__parsed_specifications<_CharT> __specs, + bool __negative = false) { switch (__specs.__std_.__type_) { case __format_spec::__type::__binary_lower_case: { array()> __array; @@ -292,15 +365,14 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0X", 16); } default: - _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parse function should have validated the type"); __libcpp_unreachable(); } } -template -_LIBCPP_HIDE_FROM_ABI auto -__format_integer(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +template +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_integer(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { // Depending on the std-format-spec string the sign and the value // might not be outputted together: // - alternate form may insert a prefix string. @@ -336,10 +408,9 @@ struct _LIBCPP_TEMPLATE_VIS __bool_strings { }; # endif -template -_LIBCPP_HIDE_FROM_ABI auto -__format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +template +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_bool(bool __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { # ifndef _LIBCPP_HAS_NO_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { const auto& __np = std::use_facet>(__ctx.locale()); @@ -354,7 +425,7 @@ __format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications< } // namespace __formatter -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_output.h b/lib/libcxx/include/__format/formatter_output.h index 467692559c..072305b6db 100644 --- a/lib/libcxx/include/__format/formatter_output.h +++ b/lib/libcxx/include/__format/formatter_output.h @@ -13,22 +13,21 @@ #include <__algorithm/ranges_copy.h> #include <__algorithm/ranges_fill_n.h> #include <__algorithm/ranges_transform.h> -#include <__chrono/statically_widen.h> +#include <__bit/countl.h> #include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/escaped_output_table.h> #include <__format/formatter.h> #include <__format/parser_std_format_spec.h> #include <__format/unicode.h> #include <__iterator/back_insert_iterator.h> -#include <__type_traits/make_unsigned.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t +#include <__memory/addressof.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include #include -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -37,7 +36,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -59,15 +58,15 @@ _LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char __c) { return __c; } -struct _LIBCPP_TYPE_VIS __padding_size_result { +struct _LIBCPP_EXPORTED_FROM_ABI __padding_size_result { size_t __before_; size_t __after_; }; _LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) { - _LIBCPP_ASSERT(__width > __size, "don't call this function when no padding is required"); - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_UNCATEGORIZED(__width > __size, "don't call this function when no padding is required"); + _LIBCPP_ASSERT_UNCATEGORIZED( __align != __format_spec::__alignment::__zero_padding, "the caller should have handled the zero-padding"); size_t __fill = __width - __size; @@ -161,70 +160,46 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) } } -template -_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first, - const char* __last, string&& __grouping, _CharT __sep, - __format_spec::__parsed_specifications<_CharT> __specs) { - int __size = (__first - __begin) + // [sign][prefix] - (__last - __first) + // data - (__grouping.size() - 1); // number of separator characters +# ifndef _LIBCPP_HAS_NO_UNICODE +template <__fmt_char_type _CharT, output_iterator _OutIt> + requires(same_as<_CharT, char>) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + std::size_t __bytes = std::countl_one(static_cast(__value.__data[0])); + if (__bytes == 0) + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); - __padding_size_result __padding = {0, 0}; - if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) { - // Write [sign][prefix]. - __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); - - if (__specs.__width_ > __size) { - // Write zero padding. - __padding.__before_ = __specs.__width_ - __size; - __out_it = __formatter::__fill(_VSTD::move(__out_it), __specs.__width_ - __size, _CharT('0')); - } - } else { - if (__specs.__width_ > __size) { - // Determine padding and write padding. - __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); - - __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); - } - // Write [sign][prefix]. - __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); - } - - auto __r = __grouping.rbegin(); - auto __e = __grouping.rend() - 1; - _LIBCPP_ASSERT(__r != __e, "The slow grouping formatting is used while " - "there will be no separators written."); - // The output is divided in small groups of numbers to write: - // - A group before the first separator. - // - A separator and a group, repeated for the number of separators. - // - A group after the last separator. - // This loop achieves that process by testing the termination condition - // midway in the loop. - // - // TODO FMT This loop evaluates the loop invariant `__parser.__type != - // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test - // happens in the __write call.) Benchmark whether making two loops and - // hoisting the invariant is worth the effort. - while (true) { - if (__specs.__std_.__type_ == __format_spec::__type::__hexadecimal_upper_case) { - __last = __first + *__r; - __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __hex_to_upper); - __first = __last; - } else { - __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); - __first += *__r; - } - - if (__r == __e) - break; - - ++__r; - *__out_it++ = __sep; - } - - return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); + for (size_t __i = 0; __i < __n; ++__i) + __out_it = __formatter::__copy( + std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + __bytes, std::move(__out_it)); + return __out_it; } +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <__fmt_char_type _CharT, output_iterator _OutIt> + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + if (!__unicode::__is_high_surrogate(__value.__data[0])) + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); + + for (size_t __i = 0; __i < __n; ++__i) + __out_it = __formatter::__copy( + std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + 2, std::move(__out_it)); + return __out_it; +} + +template <__fmt_char_type _CharT, output_iterator _OutIt> + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); +} +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# else // _LIBCPP_HAS_NO_UNICODE +template <__fmt_char_type _CharT, output_iterator _OutIt> +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); +} +# endif // _LIBCPP_HAS_NO_UNICODE + /// Writes the input to the output with the required padding. /// /// Since the output column width is specified the function can be used for @@ -261,27 +236,27 @@ __write(basic_string_view<_CharT> __str, return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -template +template _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, ptrdiff_t __size) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); return __formatter::__write(basic_string_view{__first, __last}, _VSTD::move(__out_it), __specs, __size); } /// \overload /// /// Calls the function above where \a __size = \a __last - \a __first. -template +template _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); return __formatter::__write(__first, __last, _VSTD::move(__out_it), __specs, __last - __first); } @@ -290,7 +265,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha output_iterator auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, _UnaryOperation __op) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); ptrdiff_t __size = __last - __first; if (__size >= __specs.__width_) @@ -302,35 +277,6 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -/// Writes additional zero's for the precision before the exponent. -/// This is used when the precision requested in the format string is larger -/// than the maximum precision of the floating-point type. These precision -/// digits are always 0. -/// -/// \param __exponent The location of the exponent character. -/// \param __num_trailing_zeros The number of 0's to write before the exponent -/// character. -template -_LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( - const _CharT* __first, - const _CharT* __last, - output_iterator auto __out_it, - __format_spec::__parsed_specifications<_ParserCharT> __specs, - size_t __size, - const _CharT* __exponent, - size_t __num_trailing_zeros) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); - _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used"); - - __padding_size_result __padding = - __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); - __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); - __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); - __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); - __out_it = __formatter::__copy(__exponent, __last, _VSTD::move(__out_it)); - return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); -} - /// Writes a string using format's width estimation algorithm. /// /// \pre !__specs.__has_precision() @@ -342,7 +288,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( basic_string_view<_CharT> __str, output_iterator auto __out_it, __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - _LIBCPP_ASSERT(!__specs.__has_precision(), "use __write_string"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__specs.__has_precision(), "use __write_string"); // No padding -> copy the string if (!__specs.__has_width()) @@ -359,211 +305,15 @@ _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( template _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { - __format_spec::__column_width_result<_CharT> __result = + __format_spec::__column_width_result __result = __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; return __result.__width_; } -/// Writes a string using format's width estimation algorithm. -/// -/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the -/// input is ASCII. -template -_LIBCPP_HIDE_FROM_ABI auto __write_string( - basic_string_view<_CharT> __str, - output_iterator auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - if (!__specs.__has_precision()) - return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); - - int __size = __formatter::__truncate(__str, __specs.__precision_); - - return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); -} - -# if _LIBCPP_STD_VER > 20 - -struct __nul_terminator {}; - -template -_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { - return *__cstr == _CharT('\0'); -} - -template -_LIBCPP_HIDE_FROM_ABI void -__write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { - back_insert_iterator __out_it{__str}; - std::ranges::copy(__prefix, __nul_terminator{}, __out_it); - - char __buffer[8]; - to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); - std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it); - - __str += _CharT('}'); -} - -// [format.string.escaped]/2.2.1.2 -// ... -// then the sequence \u{hex-digit-sequence} is appended to E, where -// hex-digit-sequence is the shortest hexadecimal representation of C using -// lower-case hexadecimal digits. -template -_LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); -} - -// [format.string.escaped]/2.2.3 -// Otherwise (X is a sequence of ill-formed code units), each code unit U is -// appended to E in order as the sequence \x{hex-digit-sequence}, where -// hex-digit-sequence is the shortest hexadecimal representation of U using -// lower-case hexadecimal digits. -template -_LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); -} - -template -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { -# ifdef _LIBCPP_HAS_NO_UNICODE - // For ASCII assume everything above 127 is printable. - if (__value > 127) - return false; -# endif - - if (!__escaped_output_table::__needs_escape(__value)) - return false; - - __formatter::__write_well_formed_escaped_code_unit(__str, __value); - return true; -} - -template -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) { - return static_cast>(__value); -} - -enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; - -// [format.string.escaped]/2 -template -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool -__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { - // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] - switch (__value) { - case _CharT('\t'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t"); - return true; - case _CharT('\n'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n"); - return true; - case _CharT('\r'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r"); - return true; - case _CharT('\''): - if (__mark == __escape_quotation_mark::__apostrophe) - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')"); - else - __str += __value; - return true; - case _CharT('"'): - if (__mark == __escape_quotation_mark::__double_quote) - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")"); - else - __str += __value; - return true; - case _CharT('\\'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)"); - return true; - - // 2.2.1.2 - Space - case _CharT(' '): - __str += __value; - return true; - } - - // 2.2.2 - // Otherwise, if X is a shift sequence, the effect on E and further - // decoding of S is unspecified. - // For now shift sequences are ignored and treated as Unicode. Other parts - // of the format library do the same. It's unknown how ostream treats them. - // TODO FMT determine what to do with shift sequences. - - // 2.2.1.2.1 and 2.2.1.2.2 - Escape - return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); -} - -template -_LIBCPP_HIDE_FROM_ABI void -__escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { - __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; - - while (!__view.__at_end()) { - const _CharT* __first = __view.__position(); - typename __unicode::__consume_p2286_result __result = __view.__consume_p2286(); - if (__result.__ill_formed_size == 0) { - if (!__formatter::__is_escaped_sequence_written(__str, __result.__value, __mark)) - // 2.2.1.3 - Add the character - ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); - - } else { - // 2.2.3 sequence of ill-formed code units - // The number of code-units in __result.__value depends on the character type being used. - if constexpr (sizeof(_CharT) == 1) { - _LIBCPP_ASSERT(__result.__ill_formed_size == 1 || __result.__ill_formed_size == 4, - "illegal number of invalid code units."); - if (__result.__ill_formed_size == 1) // ill-formed, one code unit - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xff); - else { // out of valid range, four code units - // The code point was properly encoded, decode the value. - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value >> 18 | 0xf0); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 12 & 0x3f) | 0x80); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 6 & 0x3f) | 0x80); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value & 0x3f) | 0x80); - } - } else if constexpr (sizeof(_CharT) == 2) { - _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-16 at most one invalid code unit"); - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xffff); - } else { - static_assert(sizeof(_CharT) == 4, "unsupported character width"); - _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-32 one code unit is one code point"); - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value); - } - } - } -} - -template -_LIBCPP_HIDE_FROM_ABI auto -__format_escaped_char(_CharT __value, - output_iterator auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - basic_string<_CharT> __str; - __str += _CharT('\''); - __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe); - __str += _CharT('\''); - return __formatter::__write(__str.data(), __str.data() + __str.size(), _VSTD::move(__out_it), __specs, __str.size()); -} - -template -_LIBCPP_HIDE_FROM_ABI auto -__format_escaped_string(basic_string_view<_CharT> __values, - output_iterator auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - basic_string<_CharT> __str; - __str += _CharT('"'); - __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote); - __str += _CharT('"'); - return __formatter::__write_string(basic_string_view{__str}, _VSTD::move(__out_it), __specs); -} - -# endif // _LIBCPP_STD_VER > 20 - } // namespace __formatter -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_pointer.h b/lib/libcxx/include/__format/formatter_pointer.h index 31b49e17ab..a2212611df 100644 --- a/lib/libcxx/include/__format/formatter_pointer.h +++ b/lib/libcxx/include/__format/formatter_pointer.h @@ -27,24 +27,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_pointer { public: - constexpr __formatter_pointer() { __parser_.__alignment_ = __format_spec::__alignment::__right; } - - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_pointer); - __format_spec::__process_display_type_pointer(__parser_.__type_); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_pointer); + __format_spec::__process_display_type_pointer(__parser_.__type_, "a pointer"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(const void* __ptr, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const void* __ptr, _FormatContext& __ctx) const { __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); __specs.__std_.__alternate_form_ = true; - __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case; + __specs.__std_.__type_ = + __specs.__std_.__type_ == __format_spec::__type::__pointer_upper_case + ? __format_spec::__type::__hexadecimal_upper_case + : __format_spec::__type::__hexadecimal_lower_case; + return __formatter::__format_integer(reinterpret_cast(__ptr), __ctx, __specs); } @@ -57,16 +60,16 @@ public: // - template<> struct formatter; // - template<> struct formatter; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter : public __formatter_pointer<_CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> { }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_pointer<_CharT> {}; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_string.h b/lib/libcxx/include/__format/formatter_string.h index 606fb79249..ba64a64af8 100644 --- a/lib/libcxx/include/__format/formatter_string.h +++ b/lib/libcxx/include/__format/formatter_string.h @@ -17,7 +17,7 @@ #include <__format/formatter.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> -#include <__utility/move.h> +#include <__format/write_escaped.h> #include #include @@ -27,20 +27,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_string { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_string); + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_string); __format_spec::__process_display_type_string(__parser_.__type_); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, auto& __ctx) const -> decltype(__ctx.out()) { -# if _LIBCPP_STD_VER > 20 + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(basic_string_view<_CharT> __str, _FormatContext& __ctx) const { +# if _LIBCPP_STD_VER >= 23 if (__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); # endif @@ -48,7 +50,7 @@ public: return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } # endif @@ -57,16 +59,17 @@ public: // Formatter const char*. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter +struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(const _CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { - _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " - "prevented an invalid pointer."); + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__str, "The basic_format_arg constructor should have " + "prevented an invalid pointer."); __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 if (_Base::__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); # endif @@ -95,45 +98,38 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT*, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter { using _Base = formatter; - _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { return _Base::format(__str, __ctx); } }; // Formatter char[]. template <__fmt_char_type _CharT, size_t _Size> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT[_Size], _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(_CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { - return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); - } -}; - -// Formatter const char[]. -template <__fmt_char_type _CharT, size_t _Size> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter - : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; - - _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { + 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); } }; // Formatter std::string. template <__fmt_char_type _CharT, class _Traits, class _Allocator> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) const - -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(const basic_string<_CharT, _Traits, _Allocator>& __str, _FormatContext& __ctx) const { // Drop _Traits and _Allocator to have one std::basic_string formatter. return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); } @@ -141,18 +137,19 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT, _Traits> __str, auto& __ctx) const - -> decltype(__ctx.out()) { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(basic_string_view<_CharT, _Traits> __str, _FormatContext& __ctx) const { // Drop _Traits to have one std::basic_string_view formatter. return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); } }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_tuple.h b/lib/libcxx/include/__format/formatter_tuple.h index 82f5ada6e0..030097a879 100644 --- a/lib/libcxx/include/__format/formatter_tuple.h +++ b/lib/libcxx/include/__format/formatter_tuple.h @@ -11,18 +11,16 @@ #define _LIBCPP___FORMAT_FORMATTER_TUPLE_H #include <__algorithm/ranges_copy.h> -#include <__availability> #include <__chrono/statically_widen.h> #include <__config> +#include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> -#include <__iterator/back_insert_iterator.h> #include <__type_traits/remove_cvref.h> #include <__utility/integer_sequence.h> #include <__utility/pair.h> @@ -35,49 +33,52 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <__fmt_char_type _CharT, class _Tuple, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { +struct _LIBCPP_TEMPLATE_VIS __formatter_tuple { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __opening_bracket_ = __opening_bracket; __closing_bracket_ = __closing_bracket; } template - _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple); + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + auto __begin = __parser_.__parse(__ctx, __format_spec::__fields_tuple); - // [format.tuple]/7 - // ... For each element e in underlying_, if e.set_debug_format() - // is a valid expression, calls e.set_debug_format(). - // TODO FMT this can be removed when P2733 is accepted. - std::__for_each_index_sequence(make_index_sequence(), [&] { - std::__set_debug_format(std::get<_Index>(__underlying_)); - }); - - const _CharT* __end = __parse_ctx.end(); - if (__begin == __end) - return __begin; - - if (*__begin == _CharT('m')) { + auto __end = __ctx.end(); + // Note 'n' is part of the type here + if (__parser_.__clear_brackets_) + set_brackets({}, {}); + else if (__begin != __end && *__begin == _CharT('m')) { if constexpr (sizeof...(_Args) == 2) { set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); set_brackets({}, {}); ++__begin; } else - std::__throw_format_error("The format specifier m requires a pair or a two-element tuple"); - } else if (*__begin == _CharT('n')) { - set_brackets({}, {}); - ++__begin; + std::__throw_format_error("Type m requires a pair or a tuple with two elements"); } if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + + __ctx.advance_to(__begin); + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + std::__for_each_index_sequence(make_index_sequence(), [&] { + auto& __formatter = std::get<_Index>(__underlying_); + __formatter.parse(__ctx); + // Unlike the range_formatter we don't guard against evil parsers. Since + // this format-spec never has a format-spec for the underlying type + // adding the test would give additional overhead. + std::__set_debug_format(__formatter); + }); return __begin; } @@ -91,26 +92,25 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { if (!__specs.__has_width()) return __format_tuple(__tuple, __ctx); - basic_string<_CharT> __str; - - // Since the output is written to a different iterator a new context is - // created. Since the underlying formatter uses the default formatting it - // doesn't need a locale or the formatting arguments. So creating a new - // context works. - // - // This solution works for this formatter, but it will not work for the - // range_formatter. In that patch a generic solution is work in progress. - // Once that is finished it can be used here. (The range_formatter will use - // these features so it's easier to add it there and then port it.) - // - // TODO FMT Use formatting wrapping used in the range_formatter. - basic_format_context __c = std::__format_context_create( - back_insert_iterator{__str}, - basic_format_args>, _CharT>>{}); + // The size of the buffer needed is: + // - open bracket characters + // - close bracket character + // - n elements where every element may have a different size + // - (n -1) separators + // The size of the element is hard to predict, knowing the type helps but + // it depends on the format-spec. As an initial estimate we guess 6 + // characters. + // Typically both brackets are 1 character and the separator is 2 + // characters. Which means there will be + // (n - 1) * 2 + 1 + 1 = n * 2 character + // So estimate 8 times the range size as buffer. + __format::__retarget_buffer<_CharT> __buffer{8 * tuple_size_v<_Tuple>}; + basic_format_context::__iterator, _CharT> __c{ + __buffer.__make_output_iterator(), __ctx}; __format_tuple(__tuple, __c); - return __formatter::__write_string_no_precision(basic_string_view{__str}, __ctx.out(), __specs); + return __formatter::__write_string_no_precision(basic_string_view{__buffer.__view()}, __ctx.out(), __specs); } template @@ -120,35 +120,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { std::__for_each_index_sequence(make_index_sequence(), [&] { if constexpr (_Index) __ctx.advance_to(std::ranges::copy(__separator_, __ctx.out()).out); - - // During review Victor suggested to make the exposition only - // __underlying_ member a local variable. Currently the Standard - // requires nested debug-enabled formatter specializations not to - // output escaped output. P2733 fixes that bug, once accepted the - // code below can be used. - // (Note when a paper allows parsing a tuple-underlying-spec the - // exposition only member needs to be a class member. Earlier - // revisions of P2286 proposed that, but this was not pursued, - // due to time constrains and complexity of the matter.) - // TODO FMT This can be updated after P2733 is accepted. -# if 0 - // P2286 uses an exposition only member in the formatter - // tuple, _CharT>...> __underlying_; - // This was used in earlier versions of the paper since - // __underlying_.parse(...) was called. This is no longer the case - // so we can reduce the scope of the formatter. - // - // It does require the underlying's parse effect to be moved here too. - using _Arg = tuple_element<_Index, decltype(__tuple)>; - formatter, _CharT> __underlying; - - // [format.tuple]/7 - // ... For each element e in underlying_, if e.set_debug_format() - // is a valid expression, calls e.set_debug_format(). - std::__set_debug_format(__underlying); -# else __ctx.advance_to(std::get<_Index>(__underlying_).format(std::get<_Index>(__tuple), __ctx)); -# endif }); return std::ranges::copy(__closing_bracket_, __ctx.out()).out; @@ -164,14 +136,14 @@ private: }; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/parser_std_format_spec.h b/lib/libcxx/include/__format/parser_std_format_spec.h index c03cec9796..c01e5866a4 100644 --- a/lib/libcxx/include/__format/parser_std_format_spec.h +++ b/lib/libcxx/include/__format/parser_std_format_spec.h @@ -16,23 +16,28 @@ /// This header has some support for the chrono-format-spec since it doesn't /// affect the std-format-spec. -#include <__algorithm/find_if.h> +#include <__algorithm/copy_n.h> #include <__algorithm/min.h> #include <__assert> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> -#include <__debug> #include <__format/format_arg.h> #include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> #include <__format/unicode.h> +#include <__format/width_estimation_table.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t +#include <__memory/addressof.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_trivially_copyable.h> #include <__variant/monostate.h> -#include #include +#include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,24 +48,36 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format_spec { -template -_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void +__throw_invalid_option_format_error(const char* __id, const char* __option) { + std::__throw_format_error( + (string("The format specifier for ") + __id + " does not allow the " + __option + " option").c_str()); +} + +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __throw_invalid_type_format_error(const char* __id) { + std::__throw_format_error( + (string("The type option contains an invalid value for ") + __id + " formatting argument").c_str()); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, _ParseContext& __ctx) { + using _CharT = iter_value_t<_Iterator>; // This function is a wrapper to call the real parser. But it does the // validation for the pre-conditions and post-conditions. if (__begin == __end) - std::__throw_format_error("End of input while parsing format-spec arg-id"); + std::__throw_format_error("End of input while parsing an argument index"); - __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); + __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __ctx); - if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) - std::__throw_format_error("Invalid arg-id"); + if (__r.__last == __end || *__r.__last != _CharT('}')) + std::__throw_format_error("The argument index is invalid"); - ++__r.__ptr; + ++__r.__last; return __r; } @@ -78,22 +95,33 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { return _VSTD::__visit_format_arg( [](auto __arg) -> uint32_t { using _Type = decltype(__arg); - if constexpr (integral<_Type>) { + if constexpr (same_as<_Type, monostate>) + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); + + // [format.string.std]/8 + // If { arg-idopt } is used in a width or precision, the value of the + // corresponding formatting argument is used in its place. If the + // corresponding formatting argument is not of standard signed or unsigned + // integer type, or its value is negative for precision or non-positive for + // width, an exception of type format_error is thrown. + // + // When an integral is used in a format function, it is stored as one of + // the types checked below. Other integral types are promoted. For example, + // a signed char is stored as an int. + if constexpr (same_as<_Type, int> || same_as<_Type, unsigned int> || // + same_as<_Type, long long> || same_as<_Type, unsigned long long>) { if constexpr (signed_integral<_Type>) { if (__arg < 0) - std::__throw_format_error("A format-spec arg-id replacement shouldn't have a negative value"); + std::__throw_format_error("An argument index may not have a negative value"); } using _CT = common_type_t<_Type, decltype(__format::__number_max)>; - if (static_cast<_CT>(__arg) > - static_cast<_CT>(__format::__number_max)) - std::__throw_format_error("A format-spec arg-id replacement exceeds the maximum supported value"); + if (static_cast<_CT>(__arg) > static_cast<_CT>(__format::__number_max)) + std::__throw_format_error("The value of the argument index exceeds its maximum value"); return __arg; - } else if constexpr (same_as<_Type, monostate>) - std::__throw_format_error("Argument index out of bounds"); - else - std::__throw_format_error("A format-spec arg-id replacement argument isn't an integral type"); + } else + std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); }, __format_arg); } @@ -104,42 +132,48 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { /// explicitly. // TODO FMT Use an ABI tag for this struct. struct __fields { - uint8_t __sign_ : 1 {false}; - uint8_t __alternate_form_ : 1 {false}; - uint8_t __zero_padding_ : 1 {false}; - uint8_t __precision_ : 1 {false}; - uint8_t __locale_specific_form_ : 1 {false}; - uint8_t __type_ : 1 {false}; + uint16_t __sign_ : 1 {false}; + uint16_t __alternate_form_ : 1 {false}; + uint16_t __zero_padding_ : 1 {false}; + uint16_t __precision_ : 1 {false}; + uint16_t __locale_specific_form_ : 1 {false}; + uint16_t __type_ : 1 {false}; // Determines the valid values for fill. // // Originally the fill could be any character except { and }. Range-based // formatters use the colon to mark the beginning of the // underlying-format-spec. To avoid parsing ambiguities these formatter // specializations prohibit the use of the colon as a fill character. - uint8_t __allow_colon_in_fill_ : 1 {false}; + uint16_t __use_range_fill_ : 1 {false}; + uint16_t __clear_brackets_ : 1 {false}; + uint16_t __consume_all_ : 1 {false}; }; // By not placing this constant in the formatter class it's not duplicated for // char and wchar_t. +inline constexpr __fields __fields_bool{.__locale_specific_form_ = true, .__type_ = true, .__consume_all_ = true}; inline constexpr __fields __fields_integral{ .__sign_ = true, .__alternate_form_ = true, .__zero_padding_ = true, .__locale_specific_form_ = true, - .__type_ = true}; + .__type_ = true, + .__consume_all_ = true}; inline constexpr __fields __fields_floating_point{ .__sign_ = true, .__alternate_form_ = true, .__zero_padding_ = true, .__precision_ = true, .__locale_specific_form_ = true, - .__type_ = true}; -inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true}; -inline constexpr __fields __fields_pointer{.__type_ = true}; + .__type_ = true, + .__consume_all_ = true}; +inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true, .__consume_all_ = true}; +inline constexpr __fields __fields_pointer{.__zero_padding_ = true, .__type_ = true, .__consume_all_ = true}; -# if _LIBCPP_STD_VER > 20 -inline constexpr __fields __fields_tuple{.__type_ = false, .__allow_colon_in_fill_ = true}; -inline constexpr __fields __fields_range{.__type_ = false, .__allow_colon_in_fill_ = true}; +# if _LIBCPP_STD_VER >= 23 +inline constexpr __fields __fields_tuple{.__use_range_fill_ = true, .__clear_brackets_ = true}; +inline constexpr __fields __fields_range{.__use_range_fill_ = true, .__clear_brackets_ = true}; +inline constexpr __fields __fields_fill_align_width{}; # endif enum class _LIBCPP_ENUM_VIS __alignment : uint8_t { @@ -164,7 +198,7 @@ enum class _LIBCPP_ENUM_VIS __sign : uint8_t { }; enum class _LIBCPP_ENUM_VIS __type : uint8_t { - __default, + __default = 0, __string, __binary_lower_case, __binary_upper_case, @@ -172,7 +206,8 @@ enum class _LIBCPP_ENUM_VIS __type : uint8_t { __decimal, __hexadecimal_lower_case, __hexadecimal_upper_case, - __pointer, + __pointer_lower_case, + __pointer_upper_case, __char, __hexfloat_lower_case, __hexfloat_upper_case, @@ -185,6 +220,25 @@ enum class _LIBCPP_ENUM_VIS __type : uint8_t { __debug }; +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __create_type_mask(__type __t) { + uint32_t __shift = static_cast(__t); + if (__shift == 0) + return 1; + + if (__shift > 31) + std::__throw_format_error("The type does not fit in the mask"); + + return 1 << __shift; +} + +inline constexpr uint32_t __type_mask_integer = + __create_type_mask(__type::__binary_lower_case) | // + __create_type_mask(__type::__binary_upper_case) | // + __create_type_mask(__type::__decimal) | // + __create_type_mask(__type::__octal) | // + __create_type_mask(__type::__hexadecimal_lower_case) | // + __create_type_mask(__type::__hexadecimal_upper_case); + struct __std { __alignment __alignment_ : 3; __sign __sign_ : 2; @@ -196,6 +250,7 @@ struct __std { struct __chrono { __alignment __alignment_ : 3; bool __locale_specific_form_ : 1; + bool __hour_ : 1; bool __weekday_name_ : 1; bool __weekday_ : 1; bool __day_of_year_ : 1; @@ -203,6 +258,25 @@ struct __chrono { bool __month_name_ : 1; }; +// The fill UCS scalar value. +// +// This is always an array, with 1, 2, or 4 elements. +// The size of the data structure is always 32-bits. +template +struct __code_point; + +template <> +struct __code_point { + char __data[4] = {' '}; +}; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct __code_point { + wchar_t __data[4 / sizeof(wchar_t)] = {L' '}; +}; +# endif + /// Contains the parsed formatting specifications. /// /// This contains information for both the std-format-spec and the @@ -238,7 +312,7 @@ struct __parsed_specifications { /// replaced with the value of that arg-id. int32_t __precision_; - _CharT __fill_; + __code_point<_CharT> __fill_; _LIBCPP_HIDE_FROM_ABI constexpr bool __has_width() const { return __width_ > 0; } @@ -265,48 +339,161 @@ static_assert(is_trivially_copyable_v<__parsed_specifications>); template class _LIBCPP_TEMPLATE_VIS __parser { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields) - -> decltype(__parse_ctx.begin()) { - - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + // Parses the format specification. + // + // Depending on whether the parsing is done compile-time or run-time + // the method slightly differs. + // - Only parses a field when it is in the __fields. Accepting all + // fields and then validating the valid ones has a performance impact. + // This is faster but gives slighly worse error messages. + // - At compile-time when a field is not accepted the parser will still + // parse it and give an error when it's present. This gives a more + // accurate error. + // The idea is that most times the format instead of the vformat + // functions are used. In that case the error will be detected during + // compilation and there is no need to pay for the run-time overhead. + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) { + auto __begin = __ctx.begin(); + auto __end = __ctx.end(); if (__begin == __end) return __begin; - if (__parse_fill_align(__begin, __end, __fields.__allow_colon_in_fill_) && __begin == __end) + if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end) return __begin; - if (__fields.__sign_ && __parse_sign(__begin) && __begin == __end) - return __begin; - - if (__fields.__alternate_form_ && __parse_alternate_form(__begin) && __begin == __end) - return __begin; - - if (__fields.__zero_padding_ && __parse_zero_padding(__begin) && __begin == __end) - return __begin; - - if (__parse_width(__begin, __end, __parse_ctx) && __begin == __end) - return __begin; - - if (__fields.__precision_ && __parse_precision(__begin, __end, __parse_ctx) && __begin == __end) - return __begin; - - if (__fields.__locale_specific_form_ && __parse_locale_specific_form(__begin) && __begin == __end) - return __begin; - - if (__fields.__type_) { - __parse_type(__begin); - - // When __type_ is false the calling parser is expected to do additional - // parsing. In that case that parser should do the end of format string - // validation. - if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + if (__fields.__sign_) { + if (__parse_sign(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_sign(__begin)) { + std::__throw_format_error("The format specification does not allow the sign option"); } + if (__fields.__alternate_form_) { + if (__parse_alternate_form(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_alternate_form(__begin)) { + std::__throw_format_error("The format specifier does not allow the alternate form option"); + } + + if (__fields.__zero_padding_) { + if (__parse_zero_padding(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_zero_padding(__begin)) { + std::__throw_format_error("The format specifier does not allow the zero-padding option"); + } + + if (__parse_width(__begin, __end, __ctx) && __begin == __end) + return __begin; + + if (__fields.__precision_) { + if (__parse_precision(__begin, __end, __ctx) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_precision(__begin, __end, __ctx)) { + std::__throw_format_error("The format specifier does not allow the precision option"); + } + + if (__fields.__locale_specific_form_) { + if (__parse_locale_specific_form(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_locale_specific_form(__begin)) { + std::__throw_format_error("The format specifier does not allow the locale-specific form option"); + } + + if (__fields.__clear_brackets_) { + if (__parse_clear_brackets(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_clear_brackets(__begin)) { + std::__throw_format_error("The format specifier does not allow the n option"); + } + + if (__fields.__type_) + __parse_type(__begin); + + if (!__fields.__consume_all_) + return __begin; + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + return __begin; } + // Validates the selected the parsed data. + // + // The valid fields in the parser may depend on the display type + // selected. But the type is the last optional field, so by the time + // it's known an option can't be used, it already has been parsed. + // This does the validation again. + // + // For example an integral may have a sign, zero-padding, or alternate + // form when the type option is not 'c'. So the generic approach is: + // + // typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + // if (__parser.__type_ == __format_spec::__type::__char) { + // __parser.__validate((__format_spec::__fields_bool, "an integer"); + // ... // more char adjustments + // } else { + // ... // validate an integral type. + // } + // + // For some types all valid options need a second validation run, like + // boolean types. + // + // Depending on whether the validation is done at compile-time or + // run-time the error differs + // - run-time the exception is thrown and contains the type of field + // being validated. + // - at compile-time the line with `std::__throw_format_error` is shown + // in the output. In that case it's important for the error to be on one + // line. + // Note future versions of C++ may allow better compile-time error + // reporting. + _LIBCPP_HIDE_FROM_ABI constexpr void + __validate(__fields __fields, const char* __id, uint32_t __type_mask = -1) const { + if (!__fields.__sign_ && __sign_ != __sign::__default) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the sign option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "sign"); + } + + if (!__fields.__alternate_form_ && __alternate_form_) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the alternate form option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "alternate form"); + } + + if (!__fields.__zero_padding_ && __alignment_ == __alignment::__zero_padding) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the zero-padding option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "zero-padding"); + } + + if (!__fields.__precision_ && __precision_ != -1) { // Works both when the precision has a value or an arg-id. + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the precision option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "precision"); + } + + if (!__fields.__locale_specific_form_ && __locale_specific_form_) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the locale-specific form option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "locale-specific form"); + } + + if ((__create_type_mask(__type_) & __type_mask) == 0) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier uses an invalid value for the type option"); + else + __format_spec::__throw_invalid_type_format_error(__id); + } + } + /// \returns the `__parsed_specifications` with the resolved dynamic sizes.. _LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_std_specifications(auto& __ctx) const { @@ -326,6 +513,7 @@ public: .__chrono_ = __chrono{.__alignment_ = __alignment_, .__locale_specific_form_ = __locale_specific_form_, + .__hour_ = __hour_, .__weekday_name_ = __weekday_name_, .__weekday_ = __weekday_, .__day_of_year_ = __day_of_year_, @@ -340,11 +528,13 @@ public: __sign __sign_ : 2 {__sign::__default}; bool __alternate_form_ : 1 {false}; bool __locale_specific_form_ : 1 {false}; - bool __reserved_0_ : 1 {false}; + bool __clear_brackets_ : 1 {false}; __type __type_{__type::__default}; // These flags are only used for formatting chrono. Since the struct has // padding space left it's added to this structure. + bool __hour_ : 1 {false}; + bool __weekday_name_ : 1 {false}; bool __weekday_ : 1 {false}; @@ -353,8 +543,8 @@ public: bool __month_name_ : 1 {false}; - uint8_t __reserved_1_ : 3 {0}; - uint8_t __reserved_2_ : 6 {0}; + uint8_t __reserved_0_ : 2 {0}; + uint8_t __reserved_1_ : 6 {0}; // These two flags are only used internally and not part of the // __parsed_specifications. Therefore put them at the end. bool __width_as_arg_ : 1 {false}; @@ -366,11 +556,7 @@ public: /// The requested precision, either the value or the arg-id. int32_t __precision_{-1}; - // LWG 3576 will probably change this to always accept a Unicode code point - // To avoid changing the size with that change align the field so when it - // becomes 32-bit its alignment will remain the same. That also means the - // size will remain the same. (D2572 addresses the solution for LWG 3576.) - _CharT __fill_{_CharT(' ')}; + __code_point<_CharT> __fill_{}; private: _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alignment(_CharT __c) { @@ -390,19 +576,90 @@ private: return false; } + _LIBCPP_HIDE_FROM_ABI constexpr void __validate_fill_character(_CharT __fill, bool __use_range_fill) { + // The forbidden fill characters all code points formed from a single code unit, thus the + // check can be omitted when more code units are used. + if (__use_range_fill && (__fill == _CharT('{') || __fill == _CharT('}') || __fill == _CharT(':'))) + std::__throw_format_error("The fill option contains an invalid value"); + else if (__fill == _CharT('{') || __fill == _CharT('}')) + std::__throw_format_error("The fill option contains an invalid value"); + } + +# ifndef _LIBCPP_HAS_NO_UNICODE // range-fill and tuple-fill are identical - _LIBCPP_HIDE_FROM_ABI constexpr bool - __parse_fill_align(const _CharT*& __begin, const _CharT* __end, bool __use_range_fill) { - _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " - "undefined behavior by evaluating data not in the input"); + template + requires same_as<_CharT, char> +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + || (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) +# endif + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + __unicode::__code_point_view<_CharT> __view{__begin, __end}; + __unicode::__consume_result __consumed = __view.__consume(); + if (__consumed.__status != __unicode::__consume_result::__ok) + std::__throw_format_error("The format specifier contains malformed Unicode characters"); + + if (__view.__position() < __end && __parse_alignment(*__view.__position())) { + ptrdiff_t __code_units = __view.__position() - __begin; + if (__code_units == 1) + // The forbidden fill characters all are code points encoded + // in one code unit, thus the check can be omitted when more + // code units are used. + __validate_fill_character(*__begin, __use_range_fill); + + std::copy_n(__begin, __code_units, std::addressof(__fill_.__data[0])); + __begin += __code_units + 1; + return true; + } + + if (!__parse_alignment(*__begin)) + return false; + + ++__begin; + return true; + } + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + template + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + if (__begin + 1 != __end && __parse_alignment(*(__begin + 1))) { + if (!__unicode::__is_scalar_value(*__begin)) + std::__throw_format_error("The fill option contains an invalid value"); + + __validate_fill_character(*__begin, __use_range_fill); + + __fill_.__data[0] = *__begin; + __begin += 2; + return true; + } + + if (!__parse_alignment(*__begin)) + return false; + + ++__begin; + return true; + } + +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +# else // _LIBCPP_HAS_NO_UNICODE + // range-fill and tuple-fill are identical + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); if (__begin + 1 != __end) { if (__parse_alignment(*(__begin + 1))) { - if (__use_range_fill && (*__begin == _CharT('{') || *__begin == _CharT('}') || *__begin == _CharT(':'))) - std::__throw_format_error("The format-spec range-fill field contains an invalid character"); - else if (*__begin == _CharT('{') || *__begin == _CharT('}')) - std::__throw_format_error("The format-spec fill field contains an invalid character"); + __validate_fill_character(*__begin, __use_range_fill); - __fill_ = *__begin; + __fill_.__data[0] = *__begin; __begin += 2; return true; } @@ -415,7 +672,10 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(const _CharT*& __begin) { +# endif // _LIBCPP_HAS_NO_UNICODE + + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(_Iterator& __begin) { switch (*__begin) { case _CharT('-'): __sign_ = __sign::__minus; @@ -433,7 +693,8 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(_Iterator& __begin) { if (*__begin != _CharT('#')) return false; @@ -442,7 +703,8 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(_Iterator& __begin) { if (*__begin != _CharT('0')) return false; @@ -452,15 +714,16 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(_Iterator& __begin, _Iterator __end, auto& __ctx) { if (*__begin == _CharT('0')) - std::__throw_format_error("A format-spec width field shouldn't have a leading zero"); + std::__throw_format_error("The width option should not have a leading zero"); if (*__begin == _CharT('{')) { - __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __ctx); __width_as_arg_ = true; __width_ = __r.__value; - __begin = __r.__ptr; + __begin = __r.__last; return true; } @@ -469,40 +732,41 @@ private: __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __width_ = __r.__value; - _LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, " - "due to validations in this function"); - __begin = __r.__ptr; + _LIBCPP_ASSERT_UNCATEGORIZED(__width_ != 0, "A zero value isn't allowed and should be impossible, " + "due to validations in this function"); + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(const _CharT*& __begin, const _CharT* __end, - auto& __parse_ctx) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(_Iterator& __begin, _Iterator __end, auto& __ctx) { if (*__begin != _CharT('.')) return false; ++__begin; if (__begin == __end) - std::__throw_format_error("End of input while parsing format-spec precision"); + std::__throw_format_error("End of input while parsing format specifier precision"); if (*__begin == _CharT('{')) { - __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __ctx); __precision_as_arg_ = true; __precision_ = __arg_id.__value; - __begin = __arg_id.__ptr; + __begin = __arg_id.__last; return true; } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - std::__throw_format_error("The format-spec precision field doesn't contain a value or arg-id"); + std::__throw_format_error("The precision option does not contain a value or an argument index"); __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __precision_ = __r.__value; __precision_as_arg_ = false; - __begin = __r.__ptr; + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(_Iterator& __begin) { if (*__begin != _CharT('L')) return false; @@ -511,7 +775,18 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin) { + template + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_clear_brackets(_Iterator& __begin) { + if (*__begin != _CharT('n')) + return false; + + __clear_brackets_ = true; + ++__begin; + return true; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin) { // Determines the type. It does not validate whether the selected type is // valid. Most formatters have optional fields that are only allowed for // certain types. These parsers need to do validation after the type has @@ -561,7 +836,10 @@ private: __type_ = __type::__octal; break; case 'p': - __type_ = __type::__pointer; + __type_ = __type::__pointer_lower_case; + break; + case 'P': + __type_ = __type::__pointer_upper_case; break; case 's': __type_ = __type::__string; @@ -569,7 +847,7 @@ private: case 'x': __type_ = __type::__hexadecimal_lower_case; break; -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 case '?': __type_ = __type::__debug; break; @@ -611,36 +889,28 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_string(__format_spec break; default: - std::__throw_format_error("The format-spec type has a type not supported for a string argument"); + std::__throw_format_error("The type option contains an invalid value for a string formatting argument"); } } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser) { - if (__parser.__sign_ != __sign::__default) - std::__throw_format_error("A sign field isn't allowed in this format-spec"); - - if (__parser.__alternate_form_) - std::__throw_format_error("An alternate form field isn't allowed in this format-spec"); - - if (__parser.__alignment_ == __alignment::__zero_padding) - std::__throw_format_error("A zero-padding field isn't allowed in this format-spec"); - +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser, const char* __id) { + __parser.__validate(__format_spec::__fields_bool, __id); if (__parser.__alignment_ == __alignment::__default) __parser.__alignment_ = __alignment::__left; } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser) { - __format_spec::__process_display_type_bool_string(__parser); +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser, const char* __id) { + __format_spec::__process_display_type_bool_string(__parser, __id); } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__string: - __format_spec::__process_display_type_bool_string(__parser); + __format_spec::__process_display_type_bool_string(__parser, __id); break; case __format_spec::__type::__binary_lower_case: @@ -652,17 +922,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __p break; default: - std::__throw_format_error("The format-spec type has a type not supported for a bool argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__char: case __format_spec::__type::__debug: - __format_spec::__process_display_type_char(__parser); + __format_spec::__process_display_type_char(__parser, __id); break; case __format_spec::__type::__binary_lower_case: @@ -674,12 +944,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __p break; default: - std::__throw_format_error("The format-spec type has a type not supported for a char argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__binary_lower_case: @@ -691,16 +961,16 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& break; case __format_spec::__type::__char: - __format_spec::__process_display_type_char(__parser); + __format_spec::__process_display_type_char(__parser, __id); break; default: - std::__throw_format_error("The format-spec type has a type not supported for an integer argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__hexfloat_lower_case: @@ -719,33 +989,34 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_C break; default: - std::__throw_format_error("The format-spec type has a type not supported for a floating-point argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type, const char* __id) { switch (__type) { case __format_spec::__type::__default: - case __format_spec::__type::__pointer: + case __format_spec::__type::__pointer_lower_case: + case __format_spec::__type::__pointer_upper_case: break; default: - std::__throw_format_error("The format-spec type has a type not supported for a pointer argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } -template +template struct __column_width_result { /// The number of output columns. size_t __width_; /// One beyond the last code unit used in the estimation. /// /// This limits the original output to fit in the wanted number of columns. - const _CharT* __last_; + _Iterator __last_; }; -template -__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>; +template +__column_width_result(size_t, _Iterator) -> __column_width_result<_Iterator>; /// Since a column width can be two it's possible that the requested column /// width can't be achieved. Depending on the intended usage the policy can be @@ -761,66 +1032,16 @@ enum class __column_width_rounding { __down, __up }; # ifndef _LIBCPP_HAS_NO_UNICODE namespace __detail { - -/// Converts a code point to the column width. -/// -/// The estimations are conforming to [format.string.general]/11 -/// -/// This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 -/// character. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_3(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c < 0x10000, "Use __column_width_4 or __column_width for larger values"); - - // clang-format off - return 1 + (__c >= 0x1100 && (__c <= 0x115f || - (__c >= 0x2329 && (__c <= 0x232a || - (__c >= 0x2e80 && (__c <= 0x303e || - (__c >= 0x3040 && (__c <= 0xa4cf || - (__c >= 0xac00 && (__c <= 0xd7a3 || - (__c >= 0xf900 && (__c <= 0xfaff || - (__c >= 0xfe10 && (__c <= 0xfe19 || - (__c >= 0xfe30 && (__c <= 0xfe6f || - (__c >= 0xff00 && (__c <= 0xff60 || - (__c >= 0xffe0 && (__c <= 0xffe6 - )))))))))))))))))))); - // clang-format on -} - -/// @overload -/// -/// This version expects a value greater than or equal to 0x1'0000, which is a -/// 4-byte UTF-8 character. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_4(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c >= 0x10000, "Use __column_width_3 or __column_width for smaller values"); - - // clang-format off - return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || - (__c >= 0x1'f900 && (__c <= 0x1'f9ff || - (__c >= 0x2'0000 && (__c <= 0x2'fffd || - (__c >= 0x3'0000 && (__c <= 0x3'fffd - )))))))); - // clang-format on -} - -/// @overload -/// -/// The general case, accepting all values. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width(uint32_t __c) noexcept { - if (__c < 0x10000) - return __detail::__column_width_3(__c); - - return __detail::__column_width_4(__c); -} - -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( - const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { +template +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width_grapheme_clustering( + _Iterator __first, _Iterator __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + using _CharT = iter_value_t<_Iterator>; __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; - __column_width_result<_CharT> __result{0, __first}; + __column_width_result<_Iterator> __result{0, __first}; while (__result.__last_ != __last && __result.__width_ <= __maximum) { typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); - int __width = __detail::__column_width(__cluster.__code_point_); + int __width = __width_estimation_table::__estimated_width(__cluster.__code_point_); // When the next entry would exceed the maximum width the previous width // might be returned. For example when a width of 100 is requested the @@ -884,8 +1105,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_ascii(char32_t __c) { return __c < 0x8 /// \param __rounding Selects the rounding method. /// \c __down result.__width_ <= __maximum /// \c __up result.__width_ <= __maximum + 1 -template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( +template ::const_iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width( basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { // The width estimation is done in two steps: // - Quickly process for the ASCII part. ASCII has the following properties @@ -904,7 +1125,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ // need to scan one code unit beyond the requested precision. When this code // unit is non-ASCII we omit the current code unit and let the Grapheme // clustering algorithm do its work. - const _CharT* __it = __str.begin(); + auto __it = __str.begin(); if (__format_spec::__is_ascii(*__it)) { do { --__maximum; @@ -932,7 +1153,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ } # else // !defined(_LIBCPP_HAS_NO_UNICODE) template -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result::const_iterator> __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { // When Unicode isn't supported assume ASCII and every code unit is one code // point. In ASCII the estimated column width is always one. Thus there's no @@ -945,7 +1166,7 @@ __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __col } // namespace __format_spec -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/range_default_formatter.h b/lib/libcxx/include/__format/range_default_formatter.h index 774887b053..bcab5d6afd 100644 --- a/lib/libcxx/include/__format/range_default_formatter.h +++ b/lib/libcxx/include/__format/range_default_formatter.h @@ -14,22 +14,25 @@ # pragma GCC system_header #endif -#include <__availability> +#include <__algorithm/ranges_copy.h> #include <__chrono/statically_widen.h> #include <__concepts/same_as.h> #include <__config> #include <__format/concepts.h> #include <__format/formatter.h> #include <__format/range_formatter.h> +#include <__iterator/back_insert_iterator.h> #include <__ranges/concepts.h> +#include <__ranges/data.h> +#include <__ranges/size.h> +#include <__type_traits/conditional.h> #include <__type_traits/remove_cvref.h> #include <__utility/pair.h> #include -#include _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template concept __const_formattable_range = @@ -83,40 +86,23 @@ inline constexpr range_format format_kind<_Rp> = [] { return range_format::sequence; }(); -// This is a non-standard work-around to fix instantiation of -// formatter -// const _CharT[N] satisfies the ranges::input_range concept. -// remove_cvref_t is _CharT[N] so it does not satisfy the -// requirement of the above specialization. Instead it will instantiate the -// primary template, which is ill-formed. -// -// An alternative solution is to remove the offending formatter. -// -// https://godbolt.org/z/bqjhhaexx -// -// The removal is proposed in LWG3833, but use the work-around until the issue -// has been adopted. -// TODO FMT Implement LWG3833. -template -inline constexpr range_format format_kind = range_format::disabled; - template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter; +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; // Required specializations template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; range_formatter>, _CharT> __underlying_; public: - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __underlying_.set_separator(__separator); } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __underlying_.set_brackets(__opening_bracket, __closing_bracket); } @@ -125,14 +111,15 @@ public: return __underlying_.parse(__ctx); } - template - _LIBCPP_HIDE_FROM_ABI typename FormatContext::iterator format(__maybe_const_r& __range, FormatContext& __ctx) const { + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_r& __range, _FormatContext& __ctx) const { return __underlying_.format(__range, __ctx); } }; template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; using __element_type = remove_cvref_t>; @@ -160,7 +147,7 @@ public: }; template -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; using __element_type = remove_cvref_t>; @@ -185,16 +172,48 @@ public: template requires(_Kp == range_format::string || _Kp == range_format::debug_string) -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<_Kp, _Rp, _CharT> { - __range_default_formatter() = delete; // TODO FMT Implement +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<_Kp, _Rp, _CharT> { +private: + // This deviates from the Standard, there the exposition only type is + // formatter, charT> underlying_; + // Using a string_view allows the format function to avoid a copy of the + // input range when it is a contigious range. + formatter, _CharT> __underlying_; + +public: + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __i = __underlying_.parse(__ctx); + if constexpr (_Kp == range_format::debug_string) + __underlying_.set_debug_format(); + return __i; + } + + template + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(conditional_t, const _Rp&, _Rp&> __range, _FormatContext& __ctx) const { + // When the range is contiguous use a basic_string_view instead to avoid a + // copy of the underlying data. The basic_string_view formatter + // specialization is the "basic" string formatter in libc++. + if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) + return __underlying_.format(basic_string_view<_CharT>{ranges::data(__range), ranges::size(__range)}, __ctx); + else { + // P2106's from_range has not been implemented yet. Instead use a simple + // copy operation. + // TODO FMT use basic_string's "from_range" constructor. + // return __underlying_.format(basic_string<_CharT>{from_range, __range}, __ctx); + basic_string<_CharT> __str; + std::ranges::copy(__range, back_insert_iterator{__str}); + return __underlying_.format(static_cast>(__str), __ctx); + } + } }; template requires(format_kind<_Rp> != range_format::disabled && formattable, _CharT>) -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Rp, _CharT> - : __range_default_formatter, _Rp, _CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter, _Rp, _CharT> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/range_formatter.h b/lib/libcxx/include/__format/range_formatter.h index 9ea61a7035..27870972c9 100644 --- a/lib/libcxx/include/__format/range_formatter.h +++ b/lib/libcxx/include/__format/range_formatter.h @@ -15,13 +15,11 @@ #endif #include <__algorithm/ranges_copy.h> -#include <__availability> #include <__chrono/statically_widen.h> #include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/formatter.h> @@ -36,54 +34,73 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template requires same_as, _Tp> && formattable<_Tp, _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { +struct _LIBCPP_TEMPLATE_VIS range_formatter { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __opening_bracket_ = __opening_bracket; __closing_bracket_ = __closing_bracket; } - _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() { return __underlying_; } - _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() noexcept { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const noexcept { return __underlying_; } template - _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range); - const _CharT* __end = __parse_ctx.end(); - if (__begin == __end) - return __begin; + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + auto __begin = __parser_.__parse(__ctx, __format_spec::__fields_range); + auto __end = __ctx.end(); + // Note the cases where __begin == __end in this code only happens when the + // replacement-field has no terminating }, or when the parse is manually + // called with a format-spec. The former is an error and the latter means + // using a formatter without the format functions or print. + if (__begin == __end) [[unlikely]] + return __parse_empty_range_underlying_spec(__ctx, __begin); // The n field overrides a possible m type, therefore delay applying the // effect of n until the type has been procesed. - bool __clear_brackets = (*__begin == _CharT('n')); - if (__clear_brackets) { - ++__begin; - if (__begin == __end) { - // Since there is no more data, clear the brackets before returning. - set_brackets({}, {}); - return __begin; - } - } - __parse_type(__begin, __end); - if (__clear_brackets) + if (__parser_.__clear_brackets_) set_brackets({}, {}); - if (__begin == __end) - return __begin; + if (__begin == __end) [[unlikely]] + return __parse_empty_range_underlying_spec(__ctx, __begin); bool __has_range_underlying_spec = *__begin == _CharT(':'); + if (__has_range_underlying_spec) { + // range-underlying-spec: + // : format-spec + ++__begin; + } else if (__begin != __end && *__begin != _CharT('}')) + // When there is no underlaying range the current parse should have + // consumed the format-spec. If not, the not consumed input will be + // processed by the underlying. For example {:-} for a range in invalid, + // the sign field is not present. Without this check the underlying_ will + // get -} as input which my be valid. + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + + __ctx.advance_to(__begin); + __begin = __underlying_.parse(__ctx); + + // This test should not be required if __has_range_underlying_spec is false. + // However this test makes sure the underlying formatter left the parser in + // a valid state. (Note this is not a full protection against evil parsers. + // For example + // } this is test for the next argument {} + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + // could consume more than it should. + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + if (__parser_.__type_ != __format_spec::__type::__default) { // [format.range.formatter]/6 // If the range-type is s or ?s, then there shall be no n option and no // range-underlying-spec. - if (__clear_brackets) { + if (__parser_.__clear_brackets_) { if (__parser_.__type_ == __format_spec::__type::__string) std::__throw_format_error("The n option and type s can't be used together"); std::__throw_format_error("The n option and type ?s can't be used together"); @@ -96,20 +113,6 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { } else if (!__has_range_underlying_spec) std::__set_debug_format(__underlying_); - if (__has_range_underlying_spec) { - // range-underlying-spec: - // : format-spec - ++__begin; - if (__begin == __end) - return __begin; - - __parse_ctx.advance_to(__begin); - __begin = __underlying_.parse(__parse_ctx); - } - - if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); - return __begin; } @@ -211,7 +214,8 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; private: - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin, const _CharT* __end) { + template + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin, _Iterator __end) { switch (*__begin) { case _CharT('m'): if constexpr (__fmt_pair_like<_Tp>) { @@ -219,7 +223,7 @@ private: set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ", ")); ++__begin; } else - std::__throw_format_error("The range-format-spec type m requires two elements for a pair or tuple"); + std::__throw_format_error("Type m requires a pair or a tuple with two elements"); break; case _CharT('s'): @@ -227,28 +231,39 @@ private: __parser_.__type_ = __format_spec::__type::__string; ++__begin; } else - std::__throw_format_error("The range-format-spec type s requires formatting a character type"); + std::__throw_format_error("Type s requires character type as formatting argument"); break; case _CharT('?'): ++__begin; if (__begin == __end || *__begin != _CharT('s')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); if constexpr (same_as<_Tp, _CharT>) { __parser_.__type_ = __format_spec::__type::__debug; ++__begin; } else - std::__throw_format_error("The range-format-spec type ?s requires formatting a character type"); + std::__throw_format_error("Type ?s requires character type as formatting argument"); } } + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse_empty_range_underlying_spec(_ParseContext& __ctx, typename _ParseContext::iterator __begin) { + __ctx.advance_to(__begin); + [[maybe_unused]] typename _ParseContext::iterator __result = __underlying_.parse(__ctx); + _LIBCPP_ASSERT_UNCATEGORIZED( + __result == __begin, + "the underlying's parse function should not advance the input beyond the end of the input"); + return __begin; + } + formatter<_Tp, _CharT> __underlying_; basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "["); basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "]"); }; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/unicode.h b/lib/libcxx/include/__format/unicode.h index 4327258760..8666f80c78 100644 --- a/lib/libcxx/include/__format/unicode.h +++ b/lib/libcxx/include/__format/unicode.h @@ -11,11 +11,13 @@ #define _LIBCPP___FORMAT_UNICODE_H #include <__assert> +#include <__bit/countl.h> +#include <__concepts/same_as.h> #include <__config> #include <__format/extended_grapheme_cluster_table.h> -#include <__type_traits/make_unsigned.h> -#include <__utility/unreachable.h> -#include +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,27 +25,32 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __unicode { -# if _LIBCPP_STD_VER > 20 +// Helper struct for the result of a consume operation. +// +// The status value for a correct code point is 0. This allows a valid value to +// be used without masking. +// When the decoding fails it know the number of code units affected. For the +// current use-cases that value is not needed, therefore it is not stored. +// The escape routine needs the number of code units for both a valid and +// invalid character and keeps track of it itself. Doing it in this result +// unconditionally would give some overhead when the value is unneeded. +struct __consume_result { + // When __status == __ok it contains the decoded code point. + // Else it contains the replacement character U+FFFD + char32_t __code_point : 31; -/// The result of consuming a code point using P2286' semantics -/// -/// TODO FMT Combine __consume and __consume_p2286 in one function. -struct __consume_p2286_result { - // A size of 0 means well formed. This to differenciate between - // a valid code point and a code unit that's invalid like 0b11111xxx. - int __ill_formed_size; - - // If well formed the consumed code point. - // Otherwise the ill-formed code units as unsigned 8-bit values. They are - // stored in reverse order, to make it easier to extract the values. - char32_t __value; + enum : char32_t { + // Consumed a well-formed code point. + __ok = 0, + // Encountered invalid UTF-8 + __error = 1 + } __status : 1 {__ok}; }; - -# endif // _LIBCPP_STD_VER > 20 +static_assert(sizeof(__consume_result) == sizeof(char32_t)); # ifndef _LIBCPP_HAS_NO_UNICODE @@ -62,9 +69,41 @@ struct __consume_p2286_result { inline constexpr char32_t __replacement_character = U'\ufffd'; -_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { +// The error of a consume operation. +// +// This sets the code point to the replacement character. This code point does +// not participate in the grapheme clustering, so grapheme clustering code can +// ignore the error status and always use the code point. +inline constexpr __consume_result __consume_result_error{__replacement_character, __consume_result::__error}; + +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_high_surrogate(char32_t __value) { + return __value >= 0xd800 && __value <= 0xdbff; +} + +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_low_surrogate(char32_t __value) { + return __value >= 0xdc00 && __value <= 0xdfff; +} + +// https://www.unicode.org/glossary/#surrogate_code_point +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_surrogate(char32_t __value) { + return __value >= 0xd800 && __value <= 0xdfff; +} + +// https://www.unicode.org/glossary/#code_point +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_code_point(char32_t __value) { + return __value <= 0x10ffff; +} + +// https://www.unicode.org/glossary/#unicode_scalar_value +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_scalar_value(char32_t __value) { + return __unicode::__is_code_point(__value) && !__unicode::__is_surrogate(__value); +} + +template + requires same_as, char> +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(_Iterator __char, int __count) { do { - if ((*__char & 0b1000'0000) != 0b1000'0000) + if ((*__char & 0b1100'0000) != 0b1000'0000) return false; --__count; ++__char; @@ -82,133 +121,116 @@ class __code_point_view; /// UTF-8 specialization. template <> class __code_point_view { + using _Iterator = basic_string_view::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); - - // Based on the number of leading 1 bits the number of code units in the - // code point can be determined. See - // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (_VSTD::countl_one(static_cast(*__first_))) { - case 0: - return *__first_++; - - case 2: - if (__last_ - __first_ < 2 || !__unicode::__is_continuation(__first_ + 1, 1)) [[unlikely]] - break; - else { - char32_t __value = static_cast(*__first_++) & 0x1f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - return __value; - } - - case 3: - if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] - break; - else { - char32_t __value = static_cast(*__first_++) & 0x0f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - return __value; - } - - case 4: - if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] - break; - else { - char32_t __value = static_cast(*__first_++) & 0x07; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - return __value; - } - } - // An invalid number of leading ones can be garbage or a code unit in the - // middle of a code point. By consuming one code unit the parser may get - // "in sync" after a few code units. - ++__first_; - return __replacement_character; - } - -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + // https://www.unicode.org/versions/latest/ch03.pdf#G7404 + // Based on Table 3-7, Well-Formed UTF-8 Byte Sequences + // + // Code Points First Byte Second Byte Third Byte Fourth Byte Remarks + // U+0000..U+007F 00..7F U+0000..U+007F 1 code unit range + // C0..C1 80..BF invalid overlong encoding + // U+0080..U+07FF C2..DF 80..BF U+0080..U+07FF 2 code unit range + // E0 80..9F 80..BF invalid overlong encoding + // U+0800..U+0FFF E0 A0..BF 80..BF U+0800..U+FFFF 3 code unit range + // U+1000..U+CFFF E1..EC 80..BF 80..BF + // U+D000..U+D7FF ED 80..9F 80..BF + // U+D800..U+DFFF ED A0..BF 80..BF invalid encoding of surrogate code point + // U+E000..U+FFFF EE..EF 80..BF 80..BF + // F0 80..8F 80..BF 80..BF invalid overlong encoding + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF U+10000..U+10FFFF 4 code unit range + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + // F4 90..BF 80..BF 80..BF U+110000.. invalid code point range + // + // Unlike other parsers, these invalid entries are tested after decoding. + // - The parser always needs to consume these code units + // - The code is optimized for well-formed UTF-8 + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); // Based on the number of leading 1 bits the number of code units in the // code point can be determined. See // https://en.wikipedia.org/wiki/UTF-8#Encoding switch (std::countl_one(static_cast(*__first_))) { case 0: - return {0, static_cast(*__first_++)}; + return {static_cast(*__first_++)}; - case 2: - if (__last_ - __first_ < 2) [[unlikely]] + case 2: { + if (__last_ - __first_ < 2 || !__unicode::__is_continuation(__first_ + 1, 1)) [[unlikely]] break; - if (__unicode::__is_continuation(__first_ + 1, 1)) { - char32_t __value = static_cast(*__first_++) & 0x1f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - return {0, __value}; - } - break; + char32_t __value = static_cast(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; - case 3: - if (__last_ - __first_ < 3) [[unlikely]] + // These values should be encoded in 1 UTF-8 code unit. + if (__value < 0x0080) [[unlikely]] + return __consume_result_error; + + return {__value}; + } + + case 3: { + if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] break; - if (__unicode::__is_continuation(__first_ + 1, 2)) { - char32_t __value = static_cast(*__first_++) & 0x0f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - return {0, __value}; - } - break; + char32_t __value = static_cast(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; - case 4: - if (__last_ - __first_ < 4) [[unlikely]] + // These values should be encoded in 1 or 2 UTF-8 code units. + if (__value < 0x0800) [[unlikely]] + return __consume_result_error; + + // A surrogate value is always encoded in 3 UTF-8 code units. + if (__unicode::__is_surrogate(__value)) [[unlikely]] + return __consume_result_error; + + return {__value}; + } + + case 4: { + if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] break; - if (__unicode::__is_continuation(__first_ + 1, 3)) { - char32_t __value = static_cast(*__first_++) & 0x07; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast(*__first_++) & 0x3f; + char32_t __value = static_cast(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; - if (__value > 0x10FFFF) // Outside the valid Unicode range? - return {4, __value}; + // These values should be encoded in 1, 2, or 3 UTF-8 code units. + if (__value < 0x10000) [[unlikely]] + return __consume_result_error; - return {0, __value}; - } - break; + // A value too large is always encoded in 4 UTF-8 code units. + if (!__unicode::__is_code_point(__value)) [[unlikely]] + return __consume_result_error; + + return {__value}; + } } // An invalid number of leading ones can be garbage or a code unit in the // middle of a code point. By consuming one code unit the parser may get // "in sync" after a few code units. - return {1, static_cast(*__first_++)}; + ++__first_; + return __consume_result_error; } -# endif // _LIBCPP_STD_VER > 20 private: - const char* __first_; - const char* __last_; + _Iterator __first_; + _Iterator __last_; }; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -225,75 +247,48 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { /// - 4 UTF-32 (for example Linux) template <> class __code_point_view { + using _Iterator = typename basic_string_view::const_iterator; + public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} - _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); + char32_t __value = static_cast(*__first_++); if constexpr (sizeof(wchar_t) == 2) { - char32_t __result = *__first_++; - // Is the code unit part of a surrogate pair? See - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__result >= 0xd800 && __result <= 0xDfff) { - // Malformed Unicode. - if (__first_ == __last_) [[unlikely]] - return __replacement_character; + if (__unicode::__is_low_surrogate(__value)) [[unlikely]] + return __consume_result_error; - __result -= 0xd800; - __result <<= 10; - __result += *__first_++ - 0xdc00; - __result += 0x10000; + if (__unicode::__is_high_surrogate(__value)) { + if (__first_ == __last_ || !__unicode::__is_low_surrogate(static_cast(*__first_))) [[unlikely]] + return __consume_result_error; + + __value -= 0xd800; + __value <<= 10; + __value += static_cast(*__first_++) - 0xdc00; + __value += 0x10000; + + if (!__unicode::__is_code_point(__value)) [[unlikely]] + return __consume_result_error; } - return __result; - - } else if constexpr (sizeof(wchar_t) == 4) { - char32_t __result = *__first_++; - if (__result > 0x10FFFF) [[unlikely]] - return __replacement_character; - return __result; } else { - __libcpp_unreachable(); - } - } - -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); - - char32_t __result = *__first_++; - if constexpr (sizeof(wchar_t) == 2) { - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__is_surrogate_pair_high(__result)) { - // Malformed Unicode. - if (__first_ == __last_ || !__is_surrogate_pair_low(*(__first_ + 1))) [[unlikely]] - return {1, __result}; - - __result -= 0xd800; - __result <<= 10; - __result += *__first_++ - 0xdc00; - __result += 0x10000; - } else if (__is_surrogate_pair_low(__result)) - // A code point shouldn't start with the low surrogate pair - return {1, __result}; - } else { - if (__result > 0x10FFFF) [[unlikely]] - return {1, __result}; + if (!__unicode::__is_scalar_value(__value)) [[unlikely]] + return __consume_result_error; } - return {0, __result}; + return {__value}; } -# endif // _LIBCPP_STD_VER > 20 private: - const wchar_t* __first_; - const wchar_t* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -310,8 +305,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( // *** Break at the start and end of text, unless the text is empty. *** - _LIBCPP_ASSERT(__prev != __property::__sot, "should be handled in the constructor"); // GB1 - _LIBCPP_ASSERT(__prev != __property::__eot, "should be handled by our caller"); // GB2 + _LIBCPP_ASSERT_UNCATEGORIZED(__prev != __property::__sot, "should be handled in the constructor"); // GB1 + _LIBCPP_ASSERT_UNCATEGORIZED(__prev != __property::__eot, "should be handled by our caller"); // GB2 // *** Do not break between a CR and LF. Otherwise, break before and after controls. *** if (__prev == __property::__CR && __next == __property::__LF) // GB3 @@ -384,10 +379,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( /// Therefore only this code point is extracted. template class __extended_grapheme_cluster_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) : __code_point_view_(__first, __last), - __next_code_point_(__code_point_view_.__consume()), + __next_code_point_(__code_point_view_.__consume().__code_point), __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} struct __cluster { @@ -401,13 +398,14 @@ public: /// /// It's expected the caller has the start position and thus can determine /// the code unit range of the extended grapheme cluster. - const _CharT* __last_; + _Iterator __last_; }; _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_UNCATEGORIZED( __next_prop_ != __extended_grapheme_custer_property_boundary::__property::__eot, "can't move beyond the end of input"); + char32_t __code_point = __next_code_point_; if (!__code_point_view_.__at_end()) return {__code_point, __get_break()}; @@ -422,17 +420,17 @@ private: char32_t __next_code_point_; __extended_grapheme_custer_property_boundary::__property __next_prop_; - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __get_break() { bool __ri_break_allowed = true; bool __has_extened_pictographic = false; while (true) { - const _CharT* __result = __code_point_view_.__position(); + _Iterator __result = __code_point_view_.__position(); __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; if (__code_point_view_.__at_end()) { __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; return __result; } - __next_code_point_ = __code_point_view_.__consume(); + __next_code_point_ = __code_point_view_.__consume().__code_point; __next_prop_ = __extended_grapheme_custer_property_boundary::__get_property(__next_code_point_); __has_extened_pictographic |= @@ -444,8 +442,8 @@ private: } }; -template -__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>; +template +__extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cluster_view>; # else // _LIBCPP_HAS_NO_UNICODE @@ -453,36 +451,30 @@ __extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_gra // This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. template class __code_point_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); - return *__first_++; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); + return {static_cast(*__first_++)}; } -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); - - return {0, std::make_unsigned_t<_CharT>(*__first_++)}; - } -# endif // _LIBCPP_STD_VER > 20 - private: - const _CharT* __first_; - const _CharT* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_UNICODE } // namespace __unicode -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/width_estimation_table.h b/lib/libcxx/include/__format/width_estimation_table.h new file mode 100644 index 0000000000..cfb488975d --- /dev/null +++ b/lib/libcxx/include/__format/width_estimation_table.h @@ -0,0 +1,271 @@ +// -*- 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 +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utils/generate_width_estimation_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H +#define _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H + +#include <__algorithm/ranges_upper_bound.h> +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace __width_estimation_table { + +/// The entries of the characters with an estimated width of 2. +/// +/// Contains the entries for [format.string.std]/12 +/// - Any code point with the East_Asian_Width="W" or East_Asian_Width="F" +/// Derived Extracted Property as described by UAX #44 +/// - U+4DC0 - U+4DFF (Yijing Hexagram Symbols) +/// - U+1F300 - U+1F5FF (Miscellaneous Symbols and Pictographs) +/// - U+1F900 - U+1F9FF (Supplemental Symbols and Pictographs) +/// +/// The data is generated from +/// - https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt +/// - The "overrides" in [format.string.std]/12 +/// +/// The format of EastAsianWidth.txt is two fields separated by a semicolon. +/// Field 0: Unicode code point value or range of code point values +/// Field 1: East_Asian_Width property, consisting of one of the following values: +/// "A", "F", "H", "N", "Na", "W" +/// - All code points, assigned or unassigned, that are not listed +/// explicitly are given the value "N". +/// - The unassigned code points in the following blocks default to "W": +/// CJK Unified Ideographs Extension A: U+3400..U+4DBF +/// CJK Unified Ideographs: U+4E00..U+9FFF +/// CJK Compatibility Ideographs: U+F900..U+FAFF +/// - All undesignated code points in Planes 2 and 3, whether inside or +/// outside of allocated blocks, default to "W": +/// Plane 2: U+20000..U+2FFFD +/// Plane 3: U+30000..U+3FFFD +/// +/// The table is similar to the table +/// __extended_grapheme_custer_property_boundary::__entries +/// which explains the details of these classes. The only difference is this +/// table lacks a property, thus having more bits available for the size. +/// +/// The maximum code point that has an estimated width of 2 is U+3FFFD. This +/// value can be encoded in 18 bits. Thus the upper 3 bits of the code point +/// are always 0. These 3 bits are used to enlarge the offset range. This +/// optimization reduces the table in Unicode 15 from 184 to 104 entries, +/// saving 320 bytes. +/// +/// The data has 2 values: +/// - 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. +inline constexpr uint32_t __entries[108] = { + 0x0440005f /* 00001100 - 0000115f [ 96] */, // + 0x08c68001 /* 0000231a - 0000231b [ 2] */, // + 0x08ca4001 /* 00002329 - 0000232a [ 2] */, // + 0x08fa4003 /* 000023e9 - 000023ec [ 4] */, // + 0x08fc0000 /* 000023f0 - 000023f0 [ 1] */, // + 0x08fcc000 /* 000023f3 - 000023f3 [ 1] */, // + 0x097f4001 /* 000025fd - 000025fe [ 2] */, // + 0x09850001 /* 00002614 - 00002615 [ 2] */, // + 0x0992000b /* 00002648 - 00002653 [ 12] */, // + 0x099fc000 /* 0000267f - 0000267f [ 1] */, // + 0x09a4c000 /* 00002693 - 00002693 [ 1] */, // + 0x09a84000 /* 000026a1 - 000026a1 [ 1] */, // + 0x09aa8001 /* 000026aa - 000026ab [ 2] */, // + 0x09af4001 /* 000026bd - 000026be [ 2] */, // + 0x09b10001 /* 000026c4 - 000026c5 [ 2] */, // + 0x09b38000 /* 000026ce - 000026ce [ 1] */, // + 0x09b50000 /* 000026d4 - 000026d4 [ 1] */, // + 0x09ba8000 /* 000026ea - 000026ea [ 1] */, // + 0x09bc8001 /* 000026f2 - 000026f3 [ 2] */, // + 0x09bd4000 /* 000026f5 - 000026f5 [ 1] */, // + 0x09be8000 /* 000026fa - 000026fa [ 1] */, // + 0x09bf4000 /* 000026fd - 000026fd [ 1] */, // + 0x09c14000 /* 00002705 - 00002705 [ 1] */, // + 0x09c28001 /* 0000270a - 0000270b [ 2] */, // + 0x09ca0000 /* 00002728 - 00002728 [ 1] */, // + 0x09d30000 /* 0000274c - 0000274c [ 1] */, // + 0x09d38000 /* 0000274e - 0000274e [ 1] */, // + 0x09d4c002 /* 00002753 - 00002755 [ 3] */, // + 0x09d5c000 /* 00002757 - 00002757 [ 1] */, // + 0x09e54002 /* 00002795 - 00002797 [ 3] */, // + 0x09ec0000 /* 000027b0 - 000027b0 [ 1] */, // + 0x09efc000 /* 000027bf - 000027bf [ 1] */, // + 0x0ac6c001 /* 00002b1b - 00002b1c [ 2] */, // + 0x0ad40000 /* 00002b50 - 00002b50 [ 1] */, // + 0x0ad54000 /* 00002b55 - 00002b55 [ 1] */, // + 0x0ba00019 /* 00002e80 - 00002e99 [ 26] */, // + 0x0ba6c058 /* 00002e9b - 00002ef3 [ 89] */, // + 0x0bc000d5 /* 00002f00 - 00002fd5 [ 214] */, // + 0x0bfc000b /* 00002ff0 - 00002ffb [ 12] */, // + 0x0c00003e /* 00003000 - 0000303e [ 63] */, // + 0x0c104055 /* 00003041 - 00003096 [ 86] */, // + 0x0c264066 /* 00003099 - 000030ff [ 103] */, // + 0x0c41402a /* 00003105 - 0000312f [ 43] */, // + 0x0c4c405d /* 00003131 - 0000318e [ 94] */, // + 0x0c640053 /* 00003190 - 000031e3 [ 84] */, // + 0x0c7c002e /* 000031f0 - 0000321e [ 47] */, // + 0x0c880027 /* 00003220 - 00003247 [ 40] */, // + 0x0c943fff /* 00003250 - 0000724f [16384] */, // + 0x1c94323c /* 00007250 - 0000a48c [12861] */, // + 0x29240036 /* 0000a490 - 0000a4c6 [ 55] */, // + 0x2a58001c /* 0000a960 - 0000a97c [ 29] */, // + 0x2b002ba3 /* 0000ac00 - 0000d7a3 [11172] */, // + 0x3e4001ff /* 0000f900 - 0000faff [ 512] */, // + 0x3f840009 /* 0000fe10 - 0000fe19 [ 10] */, // + 0x3f8c0022 /* 0000fe30 - 0000fe52 [ 35] */, // + 0x3f950012 /* 0000fe54 - 0000fe66 [ 19] */, // + 0x3f9a0003 /* 0000fe68 - 0000fe6b [ 4] */, // + 0x3fc0405f /* 0000ff01 - 0000ff60 [ 96] */, // + 0x3ff80006 /* 0000ffe0 - 0000ffe6 [ 7] */, // + 0x5bf80004 /* 00016fe0 - 00016fe4 [ 5] */, // + 0x5bfc0001 /* 00016ff0 - 00016ff1 [ 2] */, // + 0x5c0017f7 /* 00017000 - 000187f7 [ 6136] */, // + 0x620004d5 /* 00018800 - 00018cd5 [ 1238] */, // + 0x63400008 /* 00018d00 - 00018d08 [ 9] */, // + 0x6bfc0003 /* 0001aff0 - 0001aff3 [ 4] */, // + 0x6bfd4006 /* 0001aff5 - 0001affb [ 7] */, // + 0x6bff4001 /* 0001affd - 0001affe [ 2] */, // + 0x6c000122 /* 0001b000 - 0001b122 [ 291] */, // + 0x6c4c8000 /* 0001b132 - 0001b132 [ 1] */, // + 0x6c540002 /* 0001b150 - 0001b152 [ 3] */, // + 0x6c554000 /* 0001b155 - 0001b155 [ 1] */, // + 0x6c590003 /* 0001b164 - 0001b167 [ 4] */, // + 0x6c5c018b /* 0001b170 - 0001b2fb [ 396] */, // + 0x7c010000 /* 0001f004 - 0001f004 [ 1] */, // + 0x7c33c000 /* 0001f0cf - 0001f0cf [ 1] */, // + 0x7c638000 /* 0001f18e - 0001f18e [ 1] */, // + 0x7c644009 /* 0001f191 - 0001f19a [ 10] */, // + 0x7c800002 /* 0001f200 - 0001f202 [ 3] */, // + 0x7c84002b /* 0001f210 - 0001f23b [ 44] */, // + 0x7c900008 /* 0001f240 - 0001f248 [ 9] */, // + 0x7c940001 /* 0001f250 - 0001f251 [ 2] */, // + 0x7c980005 /* 0001f260 - 0001f265 [ 6] */, // + 0x7cc0034f /* 0001f300 - 0001f64f [ 848] */, // + 0x7da00045 /* 0001f680 - 0001f6c5 [ 70] */, // + 0x7db30000 /* 0001f6cc - 0001f6cc [ 1] */, // + 0x7db40002 /* 0001f6d0 - 0001f6d2 [ 3] */, // + 0x7db54002 /* 0001f6d5 - 0001f6d7 [ 3] */, // + 0x7db70003 /* 0001f6dc - 0001f6df [ 4] */, // + 0x7dbac001 /* 0001f6eb - 0001f6ec [ 2] */, // + 0x7dbd0008 /* 0001f6f4 - 0001f6fc [ 9] */, // + 0x7df8000b /* 0001f7e0 - 0001f7eb [ 12] */, // + 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] */, // + 0x7ebc0008 /* 0001faf0 - 0001faf8 [ 9] */, // + 0x80003fff /* 00020000 - 00023fff [16384] */, // + 0x90003fff /* 00024000 - 00027fff [16384] */, // + 0xa0003fff /* 00028000 - 0002bfff [16384] */, // + 0xb0003ffd /* 0002c000 - 0002fffd [16382] */, // + 0xc0003fff /* 00030000 - 00033fff [16384] */, // + 0xd0003fff /* 00034000 - 00037fff [16384] */, // + 0xe0003fff /* 00038000 - 0003bfff [16384] */, // + 0xf0003ffd /* 0003c000 - 0003fffd [16382] */}; + +/// The upper bound entry of EastAsianWidth.txt. +/// +/// Values greater than this value may have more than 18 significant bits. +/// They always have a width of 1. This property makes it possible to store +/// the table in its compact form. +inline constexpr uint32_t __table_upper_bound = 0x0003fffd; + +/// Returns the estimated width of a Unicode code point. +/// +/// \pre The code point is a valid Unicode code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int __estimated_width(const char32_t __code_point) noexcept { + // Since __table_upper_bound contains the unshifted range do the + // comparison without shifting. + if (__code_point > __table_upper_bound) [[unlikely]] + return 1; + + // When the code-point is less than the first element in the table + // the lookup is quite expensive. Since quite some scripts are in + // that range, it makes sense to validate that first. + // The std_format_spec_string_unicode benchmark gives a measurable + // improvement. + if (__code_point < (__entries[0] >> 14)) + return 1; + + ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 14) | 0x3fffu) - __entries; + if (__i == 0) + return 1; + + --__i; + uint32_t __upper_bound = (__entries[__i] >> 14) + (__entries[__i] & 0x3fffu); + return 1 + (__code_point <= __upper_bound); +} + +} // namespace __width_estimation_table + +#endif //_LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H diff --git a/lib/libcxx/include/__format/write_escaped.h b/lib/libcxx/include/__format/write_escaped.h new file mode 100644 index 0000000000..8c51d0b1f1 --- /dev/null +++ b/lib/libcxx/include/__format/write_escaped.h @@ -0,0 +1,222 @@ +// -*- 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___FORMAT_WRITE_ESCAPED_H +#define _LIBCPP___FORMAT_WRITE_ESCAPED_H + +#include <__algorithm/ranges_copy.h> +#include <__algorithm/ranges_for_each.h> +#include <__charconv/to_chars_integral.h> +#include <__charconv/to_chars_result.h> +#include <__chrono/statically_widen.h> +#include <__format/escaped_output_table.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> +#include <__iterator/back_insert_iterator.h> +#include <__memory/addressof.h> +#include <__system_error/errc.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + + +namespace __formatter { + +#if _LIBCPP_STD_VER >= 20 + +/// Writes a string using format's width estimation algorithm. +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. +template +_LIBCPP_HIDE_FROM_ABI auto __write_string( + basic_string_view<_CharT> __str, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + if (!__specs.__has_precision()) + return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); + + int __size = __formatter::__truncate(__str, __specs.__precision_); + + return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); +} + +# endif // _LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 + +struct __nul_terminator {}; + +template +_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { + return *__cstr == _CharT('\0'); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { + back_insert_iterator __out_it{__str}; + std::ranges::copy(__prefix, __nul_terminator{}, __out_it); + + char __buffer[8]; + to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); + std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it); + + __str += _CharT('}'); +} + +// [format.string.escaped]/2.2.1.2 +// ... +// then the sequence \u{hex-digit-sequence} is appended to E, where +// hex-digit-sequence is the shortest hexadecimal representation of C using +// lower-case hexadecimal digits. +template +_LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); +} + +// [format.string.escaped]/2.2.3 +// Otherwise (X is a sequence of ill-formed code units), each code unit U is +// appended to E in order as the sequence \x{hex-digit-sequence}, where +// hex-digit-sequence is the shortest hexadecimal representation of U using +// lower-case hexadecimal digits. +template +_LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); +} + +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { +# ifdef _LIBCPP_HAS_NO_UNICODE + // For ASCII assume everything above 127 is printable. + if (__value > 127) + return false; +# endif + + if (!__escaped_output_table::__needs_escape(__value)) + return false; + + __formatter::__write_well_formed_escaped_code_unit(__str, __value); + return true; +} + +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) { + return static_cast>(__value); +} + +enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; + +// [format.string.escaped]/2 +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { + // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] + switch (__value) { + case _CharT('\t'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t"); + return true; + case _CharT('\n'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n"); + return true; + case _CharT('\r'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r"); + return true; + case _CharT('\''): + if (__mark == __escape_quotation_mark::__apostrophe) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')"); + else + __str += __value; + return true; + case _CharT('"'): + if (__mark == __escape_quotation_mark::__double_quote) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")"); + else + __str += __value; + return true; + case _CharT('\\'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)"); + return true; + + // 2.2.1.2 - Space + case _CharT(' '): + __str += __value; + return true; + } + + // 2.2.2 + // Otherwise, if X is a shift sequence, the effect on E and further + // decoding of S is unspecified. + // For now shift sequences are ignored and treated as Unicode. Other parts + // of the format library do the same. It's unknown how ostream treats them. + // TODO FMT determine what to do with shift sequences. + + // 2.2.1.2.1 and 2.2.1.2.2 - Escape + return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { + __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; + + while (!__view.__at_end()) { + auto __first = __view.__position(); + typename __unicode::__consume_result __result = __view.__consume(); + if (__result.__status == __unicode::__consume_result::__ok) { + if (!__formatter::__is_escaped_sequence_written(__str, __result.__code_point, __mark)) + // 2.2.1.3 - Add the character + ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); + } else { + // 2.2.3 sequence of ill-formed code units + ranges::for_each(__first, __view.__position(), [&](_CharT __value) { + __formatter::__write_escape_ill_formed_code_unit(__str, __formatter::__to_char32(__value)); + }); + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_char(_CharT __value, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('\''); + __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe); + __str += _CharT('\''); + return __formatter::__write(__str.data(), __str.data() + __str.size(), _VSTD::move(__out_it), __specs, __str.size()); +} + +template +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_string(basic_string_view<_CharT> __values, + output_iterator auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('"'); + __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote); + __str += _CharT('"'); + return __formatter::__write_string(basic_string_view{__str}, _VSTD::move(__out_it), __specs); +} + +# endif // _LIBCPP_STD_VER >= 23 + +} // namespace __formatter + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_WRITE_ESCAPED_H diff --git a/lib/libcxx/include/__functional/bind.h b/lib/libcxx/include/__functional/bind.h index 297e4e5103..398cb3dc34 100644 --- a/lib/libcxx/include/__functional/bind.h +++ b/lib/libcxx/include/__functional/bind.h @@ -13,9 +13,11 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/weak_result_type.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference_wrapper.h> +#include <__type_traits/is_void.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,9 +32,9 @@ struct is_bind_expression : _If< is_bind_expression<__remove_cvref_t<_Tp> > > {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template -inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; +inline constexpr bool is_bind_expression_v = is_bind_expression<_Tp>::value; #endif template @@ -42,9 +44,9 @@ struct is_placeholder : _If< is_placeholder<__remove_cvref_t<_Tp> > > {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template -inline constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; +inline constexpr int is_placeholder_v = is_placeholder<_Tp>::value; #endif namespace placeholders @@ -52,29 +54,24 @@ namespace placeholders template struct __ph {}; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -_LIBCPP_FUNC_VIS extern const __ph<1> _1; -_LIBCPP_FUNC_VIS extern const __ph<2> _2; -_LIBCPP_FUNC_VIS extern const __ph<3> _3; -_LIBCPP_FUNC_VIS extern const __ph<4> _4; -_LIBCPP_FUNC_VIS extern const __ph<5> _5; -_LIBCPP_FUNC_VIS extern const __ph<6> _6; -_LIBCPP_FUNC_VIS extern const __ph<7> _7; -_LIBCPP_FUNC_VIS extern const __ph<8> _8; -_LIBCPP_FUNC_VIS extern const __ph<9> _9; -_LIBCPP_FUNC_VIS extern const __ph<10> _10; -#else -/* inline */ constexpr __ph<1> _1{}; -/* inline */ constexpr __ph<2> _2{}; -/* inline */ constexpr __ph<3> _3{}; -/* inline */ constexpr __ph<4> _4{}; -/* inline */ constexpr __ph<5> _5{}; -/* inline */ constexpr __ph<6> _6{}; -/* inline */ constexpr __ph<7> _7{}; -/* inline */ constexpr __ph<8> _8{}; -/* inline */ constexpr __ph<9> _9{}; -/* inline */ constexpr __ph<10> _10{}; -#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) +// C++17 recommends that we implement placeholders as `inline constexpr`, but allows +// implementing them as `extern `. Libc++ implements them as +// `extern const` in all standard modes to avoid an ABI break in C++03: making them +// `inline constexpr` requires removing their definition in the shared library to +// avoid ODR violations, which is an ABI break. +// +// In practice, since placeholders are empty, `extern const` is almost impossible +// to distinguish from `inline constexpr` from a usage stand point. +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<1> _1; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<2> _2; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<3> _3; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<4> _4; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<5> _5; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<6> _6; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<7> _7; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<8> _8; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<9> _9; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<10> _10; } // namespace placeholders @@ -86,7 +83,7 @@ struct is_placeholder > #ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_wrapper<_Tp> __t, _Uj&) { @@ -94,7 +91,7 @@ __mu(reference_wrapper<_Tp> __t, _Uj&) } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { @@ -102,7 +99,7 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __enable_if_t < is_bind_expression<_Ti>::value, @@ -124,7 +121,7 @@ struct __mu_return2 }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < 0 < is_placeholder<_Ti>::value, @@ -132,12 +129,12 @@ typename enable_if >::type __mu(_Ti&, _Uj& __uj) { - const size_t _Indx = is_placeholder<_Ti>::value - 1; - return _VSTD::forward::type>(_VSTD::get<_Indx>(__uj)); + const size_t __indx = is_placeholder<_Ti>::value - 1; + return _VSTD::forward::type>(_VSTD::get<__indx>(__uj)); } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < !is_bind_expression<_Ti>::value && @@ -255,7 +252,7 @@ struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) @@ -264,11 +261,11 @@ __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, } template -class __bind : public __weak_result_type::type> +class __bind : public __weak_result_type<__decay_t<_Fp> > { protected: - typedef typename decay<_Fp>::type _Fd; - typedef tuple::type...> _Td; + using _Fd = __decay_t<_Fp>; + typedef tuple<__decay_t<_BoundArgs>...> _Td; private: _Fd __f_; _Td __bound_args_; diff --git a/lib/libcxx/include/__functional/bind_back.h b/lib/libcxx/include/__functional/bind_back.h index f0a6e49875..71dc63c86b 100644 --- a/lib/libcxx/include/__functional/bind_back.h +++ b/lib/libcxx/include/__functional/bind_back.h @@ -13,10 +13,10 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template > struct __bind_back_op; @@ -57,7 +57,7 @@ constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) -> decltype( __bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...))) { return __bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/bind_front.h b/lib/libcxx/include/__functional/bind_front.h index 22fb3a69dc..72bb664809 100644 --- a/lib/libcxx/include/__functional/bind_front.h +++ b/lib/libcxx/include/__functional/bind_front.h @@ -13,8 +13,12 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct __bind_front_op { template @@ -51,7 +55,7 @@ constexpr auto bind_front(_Fn&& __f, _Args&&... __args) { return __bind_front_t, decay_t<_Args>...>(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/binder1st.h b/lib/libcxx/include/__functional/binder1st.h index dea22c70e1..78049d13f9 100644 --- a/lib/libcxx/include/__functional/binder1st.h +++ b/lib/libcxx/include/__functional/binder1st.h @@ -21,30 +21,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) -template +template class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st - : public __unary_function + : public __unary_function { protected: - __Operation op; - typename __Operation::first_argument_type value; + _Operation op; + typename _Operation::first_argument_type value; public: - _LIBCPP_INLINE_VISIBILITY binder1st(const __Operation& __x, - const typename __Operation::first_argument_type __y) + _LIBCPP_INLINE_VISIBILITY binder1st(const _Operation& __x, + const typename _Operation::first_argument_type __y) : op(__x), value(__y) {} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (typename __Operation::second_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (typename _Operation::second_argument_type& __x) const {return op(value, __x);} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (const typename __Operation::second_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (const typename _Operation::second_argument_type& __x) const {return op(value, __x);} }; -template +template _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY -binder1st<__Operation> -bind1st(const __Operation& __op, const _Tp& __x) - {return binder1st<__Operation>(__op, __x);} +binder1st<_Operation> +bind1st(const _Operation& __op, const _Tp& __x) + {return binder1st<_Operation>(__op, __x);} #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) diff --git a/lib/libcxx/include/__functional/binder2nd.h b/lib/libcxx/include/__functional/binder2nd.h index c98a146b6a..a3227745bc 100644 --- a/lib/libcxx/include/__functional/binder2nd.h +++ b/lib/libcxx/include/__functional/binder2nd.h @@ -21,30 +21,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) -template +template class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd - : public __unary_function + : public __unary_function { protected: - __Operation op; - typename __Operation::second_argument_type value; + _Operation op; + typename _Operation::second_argument_type value; public: _LIBCPP_INLINE_VISIBILITY - binder2nd(const __Operation& __x, const typename __Operation::second_argument_type __y) + binder2nd(const _Operation& __x, const typename _Operation::second_argument_type __y) : op(__x), value(__y) {} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - ( typename __Operation::first_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + ( typename _Operation::first_argument_type& __x) const {return op(__x, value);} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (const typename __Operation::first_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (const typename _Operation::first_argument_type& __x) const {return op(__x, value);} }; -template +template _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY -binder2nd<__Operation> -bind2nd(const __Operation& __op, const _Tp& __x) - {return binder2nd<__Operation>(__op, __x);} +binder2nd<_Operation> +bind2nd(const _Operation& __op, const _Tp& __x) + {return binder2nd<_Operation>(__op, __x);} #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) diff --git a/lib/libcxx/include/__functional/boyer_moore_searcher.h b/lib/libcxx/include/__functional/boyer_moore_searcher.h index a6750893ee..0165e06281 100644 --- a/lib/libcxx/include/__functional/boyer_moore_searcher.h +++ b/lib/libcxx/include/__functional/boyer_moore_searcher.h @@ -20,12 +20,13 @@ #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 #include #include -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_PUSH_MACROS #include <__undef_macros> @@ -113,6 +114,7 @@ private: && is_same_v<_BinaryPredicate, equal_to<>>>; public: + _LIBCPP_HIDE_FROM_ABI boyer_moore_searcher(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Hash __hash = _Hash(), @@ -134,7 +136,7 @@ public: } template - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _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, @@ -158,7 +160,7 @@ private: shared_ptr __suffix_; template - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { _RandomAccessIterator2 __current = __f; const _RandomAccessIterator2 __last = __l - __pattern_length_; @@ -183,7 +185,8 @@ private: } template - void __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) { + _LIBCPP_HIDE_FROM_ABI void + __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) { const size_t __count = __last - __first; __prefix[0] = 0; @@ -199,7 +202,8 @@ private: } } - void __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) { + _LIBCPP_HIDE_FROM_ABI void + __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) { const size_t __count = __last - __first; if (__count == 0) @@ -241,6 +245,7 @@ private: && is_same_v<_Hash, hash> && is_same_v<_BinaryPredicate, equal_to<>>>; public: + _LIBCPP_HIDE_FROM_ABI boyer_moore_horspool_searcher(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Hash __hash = _Hash(), @@ -262,7 +267,7 @@ public: } template - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _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, @@ -286,7 +291,7 @@ private: shared_ptr<__skip_table_type> __skip_table_; template - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { _RandomAccessIterator2 __current = __f; const _RandomAccessIterator2 __last = __l - __pattern_length_; @@ -310,6 +315,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H diff --git a/lib/libcxx/include/__functional/compose.h b/lib/libcxx/include/__functional/compose.h index 25213f28b1..80fcd7076c 100644 --- a/lib/libcxx/include/__functional/compose.h +++ b/lib/libcxx/include/__functional/compose.h @@ -13,8 +13,8 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct __compose_op { template @@ -45,7 +45,7 @@ constexpr auto __compose(_Fn1&& __f1, _Fn2&& __f2) -> decltype( __compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2))) { return __compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2)); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/default_searcher.h b/lib/libcxx/include/__functional/default_searcher.h index e4151e589f..222b4c66e6 100644 --- a/lib/libcxx/include/__functional/default_searcher.h +++ b/lib/libcxx/include/__functional/default_searcher.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // default searcher template> @@ -50,7 +50,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(default_searcher); -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/function.h b/lib/libcxx/include/__functional/function.h index 9f92f61814..3c6e3f450d 100644 --- a/lib/libcxx/include/__functional/function.h +++ b/lib/libcxx/include/__functional/function.h @@ -12,6 +12,7 @@ #include <__assert> #include <__config> +#include <__exception/exception.h> #include <__functional/binary_function.h> #include <__functional/invoke.h> #include <__functional/unary_function.h> @@ -23,15 +24,21 @@ #include <__memory/builtin_new_allocator.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> +#include <__type_traits/is_scalar.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_void.h> #include <__type_traits/strip_signature.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> -#include +#include <__verbose_abort> #include #include -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -46,7 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") -class _LIBCPP_EXCEPTION_ABI bad_function_call +class _LIBCPP_EXPORTED_FROM_ABI bad_function_call : public exception { public: @@ -56,7 +63,7 @@ public: #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION ~bad_function_call() _NOEXCEPT override; #else - ~bad_function_call() _NOEXCEPT override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_function_call() _NOEXCEPT override {} #endif #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE @@ -68,10 +75,10 @@ _LIBCPP_DIAGNOSTIC_POP _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_function_call() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_function_call(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_function_call was thrown in -fno-exceptions mode"); #endif } @@ -201,7 +208,7 @@ class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } - static void __destroy_and_delete(__alloc_func* __f) { + _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()); @@ -245,7 +252,7 @@ public: _LIBCPP_INLINE_VISIBILITY void destroy() _NOEXCEPT { __f_.~_Target(); } - static void __destroy_and_delete(__default_alloc_func* __f) { + _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) { __f->destroy(); __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1); } @@ -300,14 +307,14 @@ public: explicit __func(_Fp&& __f, _Alloc&& __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} - virtual __base<_Rp(_ArgTypes...)>* __clone() const; - virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; - virtual void destroy() _NOEXCEPT; - virtual void destroy_deallocate() _NOEXCEPT; - virtual _Rp operator()(_ArgTypes&&... __arg); + _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); #ifndef _LIBCPP_HAS_NO_RTTI - virtual const void* target(const type_info&) const _NOEXCEPT; - virtual const std::type_info& target_type() const _NOEXCEPT; + _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; #endif // _LIBCPP_HAS_NO_RTTI }; @@ -389,7 +396,7 @@ template class __value_func<_Rp(_ArgTypes...)> typedef __base<_Rp(_ArgTypes...)> __func; __func* __f_; - _LIBCPP_NO_CFI static __func* __as_base(void* __p) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI static __func* __as_base(void* __p) { return reinterpret_cast<__func*>(__p); } @@ -427,7 +434,7 @@ template class __value_func<_Rp(_ArgTypes...)> } template ::type, __value_func>::value>::type> + class = typename enable_if, __value_func>::value>::type> _LIBCPP_INLINE_VISIBILITY explicit __value_func(_Fp&& __f) : __value_func(_VSTD::forward<_Fp>(__f), allocator<_Fp>()) {} @@ -614,33 +621,34 @@ struct __policy _LIBCPP_INLINE_VISIBILITY static const __policy* __create_empty() { - static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, - true, + static const _LIBCPP_CONSTEXPR __policy __policy = {nullptr, nullptr, + true, #ifndef _LIBCPP_HAS_NO_RTTI - &typeid(void) + &typeid(void) #else - nullptr + nullptr #endif }; - return &__policy_; + return &__policy; } private: - template static void* __large_clone(const void* __s) + template + _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) { const _Fun* __f = static_cast(__s); return __f->__clone(); } template - static void __large_destroy(void* __s) { + _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) { _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); } template _LIBCPP_INLINE_VISIBILITY static const __policy* __choose_policy(/* is_small = */ false_type) { - static const _LIBCPP_CONSTEXPR __policy __policy_ = { + static const _LIBCPP_CONSTEXPR __policy __policy = { &__large_clone<_Fun>, &__large_destroy<_Fun>, false, #ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) @@ -648,14 +656,14 @@ struct __policy nullptr #endif }; - return &__policy_; + return &__policy; } template _LIBCPP_INLINE_VISIBILITY static const __policy* __choose_policy(/* is_small = */ true_type) { - static const _LIBCPP_CONSTEXPR __policy __policy_ = { + static const _LIBCPP_CONSTEXPR __policy __policy = { nullptr, nullptr, false, #ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) @@ -663,7 +671,7 @@ struct __policy nullptr #endif }; - return &__policy_; + return &__policy; } }; @@ -699,14 +707,14 @@ struct __policy_invoker<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY explicit __policy_invoker(__Call __c) : __call_(__c) {} - static _Rp __call_empty(const __policy_storage*, + _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) { __throw_bad_function_call(); } template - static _Rp __call_impl(const __policy_storage* __buf, + _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 @@ -770,7 +778,7 @@ template class __policy_func<_Rp(_ArgTypes...)> } } - template ::type, __policy_func>::value>::type> + template , __policy_func>::value>::type> _LIBCPP_INLINE_VISIBILITY explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) { typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; @@ -915,7 +923,7 @@ public: { } virtual __base<_Rp(_ArgTypes...)>* __clone() const { - _LIBCPP_ASSERT(false, + _LIBCPP_ASSERT_INTERNAL(false, "Block pointers are just pointers, so they should always fit into " "std::function's small buffer optimization. This function should " "never be invoked."); @@ -935,7 +943,7 @@ public: } virtual void destroy_deallocate() _NOEXCEPT { - _LIBCPP_ASSERT(false, + _LIBCPP_ASSERT_INTERNAL(false, "Block pointers are just pointers, so they should always fit into " "std::function's small buffer optimization. This function should " "never be invoked."); @@ -1002,11 +1010,11 @@ public: _LIBCPP_INLINE_VISIBILITY function() _NOEXCEPT { } _LIBCPP_INLINE_VISIBILITY - function(nullptr_t) _NOEXCEPT {} - function(const function&); - function(function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI function(nullptr_t) _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI function(const function&); + _LIBCPP_HIDE_FROM_ABI function(function&&) _NOEXCEPT; template> - function(_Fp); + _LIBCPP_HIDE_FROM_ABI function(_Fp); #if _LIBCPP_STD_VER <= 14 template @@ -1016,23 +1024,23 @@ public: _LIBCPP_INLINE_VISIBILITY function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} template - function(allocator_arg_t, const _Alloc&, const function&); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, const function&); template - function(allocator_arg_t, const _Alloc&, function&&); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, function&&); template> - function(allocator_arg_t, const _Alloc& __a, _Fp __f); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc& __a, _Fp __f); #endif - function& operator=(const function&); - function& operator=(function&&) _NOEXCEPT; - function& operator=(nullptr_t) _NOEXCEPT; - template::type>> - function& operator=(_Fp&&); + _LIBCPP_HIDE_FROM_ABI function& operator=(const function&); + _LIBCPP_HIDE_FROM_ABI function& operator=(function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI function& operator=(nullptr_t) _NOEXCEPT; + template>> + _LIBCPP_HIDE_FROM_ABI function& operator=(_Fp&&); - ~function(); + _LIBCPP_HIDE_FROM_ABI ~function(); // function modifiers: - void swap(function&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void swap(function&) _NOEXCEPT; #if _LIBCPP_STD_VER <= 14 template @@ -1050,17 +1058,21 @@ public: // deleted overloads close possible hole in the type system template bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; +#if _LIBCPP_STD_VER <= 17 template bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; +#endif public: // function invocation: - _Rp operator()(_ArgTypes...) const; + _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes...) const; #ifndef _LIBCPP_HAS_NO_RTTI // function target access: - const std::type_info& target_type() const _NOEXCEPT; - template _Tp* target() _NOEXCEPT; - template const _Tp* target() const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT; + template + _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT; + template + _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT; #endif // _LIBCPP_HAS_NO_RTTI }; @@ -1188,6 +1200,8 @@ inline _LIBCPP_INLINE_VISIBILITY bool operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return !__f;} +#if _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_INLINE_VISIBILITY bool @@ -1203,6 +1217,8 @@ inline _LIBCPP_INLINE_VISIBILITY bool operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return (bool)__f;} +#endif // _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_INLINE_VISIBILITY void diff --git a/lib/libcxx/include/__functional/hash.h b/lib/libcxx/include/__functional/hash.h index 39382aa9bf..fa09748b14 100644 --- a/lib/libcxx/include/__functional/hash.h +++ b/lib/libcxx/include/__functional/hash.h @@ -13,7 +13,7 @@ #include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__fwd/hash.h> -#include <__tuple_dir/sfinae_helpers.h> +#include <__tuple/sfinae_helpers.h> #include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_default_constructible.h> #include <__type_traits/is_enum.h> @@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI _Size __loadword(const void* __p) { @@ -53,73 +53,113 @@ struct __murmur2_or_cityhash; template struct __murmur2_or_cityhash<_Size, 32> { - inline _Size operator()(const void* __key, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + _Size operator()(const void* __key, _Size __len) const { + // murmur2 + const _Size __m = 0x5bd1e995; + const _Size __r = 24; + _Size __h = __len; + const unsigned char* __data = static_cast(__key); + for (; __len >= 4; __data += 4, __len -= 4) + { + _Size __k = std::__loadword<_Size>(__data); + __k *= __m; + __k ^= __k >> __r; + __k *= __m; + __h *= __m; + __h ^= __k; + } + switch (__len) + { + case 3: + __h ^= static_cast<_Size>(__data[2] << 16); + _LIBCPP_FALLTHROUGH(); + case 2: + __h ^= static_cast<_Size>(__data[1] << 8); + _LIBCPP_FALLTHROUGH(); + case 1: + __h ^= __data[0]; + __h *= __m; + } + __h ^= __h >> 13; + __h *= __m; + __h ^= __h >> 15; + return __h; + } }; -// murmur2 -template -_Size -__murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) -{ - const _Size __m = 0x5bd1e995; - const _Size __r = 24; - _Size __h = __len; - const unsigned char* __data = static_cast(__key); - for (; __len >= 4; __data += 4, __len -= 4) - { - _Size __k = std::__loadword<_Size>(__data); - __k *= __m; - __k ^= __k >> __r; - __k *= __m; - __h *= __m; - __h ^= __k; - } - switch (__len) - { - case 3: - __h ^= static_cast<_Size>(__data[2] << 16); - _LIBCPP_FALLTHROUGH(); - case 2: - __h ^= static_cast<_Size>(__data[1] << 8); - _LIBCPP_FALLTHROUGH(); - case 1: - __h ^= __data[0]; - __h *= __m; - } - __h ^= __h >> 13; - __h *= __m; - __h ^= __h >> 15; - return __h; -} - template struct __murmur2_or_cityhash<_Size, 64> { - inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; + // cityhash64 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + _Size operator()(const void* __key, _Size __len) const { + const char* __s = static_cast(__key); + if (__len <= 32) { + if (__len <= 16) { + return __hash_len_0_to_16(__s, __len); + } else { + return __hash_len_17_to_32(__s, __len); + } + } else if (__len <= 64) { + return __hash_len_33_to_64(__s, __len); + } - private: - // Some primes between 2^63 and 2^64. - static const _Size __k0 = 0xc3a5c85c97cb3127ULL; - static const _Size __k1 = 0xb492b66fbe98f273ULL; - static const _Size __k2 = 0x9ae16a3b2f90404fULL; - static const _Size __k3 = 0xc949d7c7509e6557ULL; + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + _Size __x = std::__loadword<_Size>(__s + __len - 40); + _Size __y = std::__loadword<_Size>(__s + __len - 16) + + std::__loadword<_Size>(__s + __len - 56); + _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, + std::__loadword<_Size>(__s + __len - 24)); + pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); + pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); + __x = __x * __k1 + std::__loadword<_Size>(__s); + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + __len = (__len - 1) & ~static_cast<_Size>(63); + do { + __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; + __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; + __x ^= __w.second; + __y += __v.first + std::__loadword<_Size>(__s + 40); + __z = __rotate(__z + __w.first, 33) * __k1; + __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); + __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, + __y + std::__loadword<_Size>(__s + 16)); + _VSTD::swap(__z, __x); + __s += 64; + __len -= 64; + } while (__len != 0); + return __hash_len_16( + __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, + __hash_len_16(__v.second, __w.second) + __x); + } + + private: + // Some primes between 2^63 and 2^64. + static const _Size __k0 = 0xc3a5c85c97cb3127ULL; + static const _Size __k1 = 0xb492b66fbe98f273ULL; + static const _Size __k2 = 0x9ae16a3b2f90404fULL; + static const _Size __k3 = 0xc949d7c7509e6557ULL; + + _LIBCPP_HIDE_FROM_ABI static _Size __rotate(_Size __val, int __shift) { return __shift == 0 ? __val : ((__val >> __shift) | (__val << (64 - __shift))); } + _LIBCPP_HIDE_FROM_ABI static _Size __rotate_by_at_least_1(_Size __val, int __shift) { return (__val >> __shift) | (__val << (64 - __shift)); } + _LIBCPP_HIDE_FROM_ABI static _Size __shift_mix(_Size __val) { return __val ^ (__val >> 47); } - static _Size __hash_len_16(_Size __u, _Size __v) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_16(_Size __u, _Size __v) { const _Size __mul = 0x9ddfea08eb382d69ULL; _Size __a = (__u ^ __v) * __mul; __a ^= (__a >> 47); @@ -129,9 +169,8 @@ struct __murmur2_or_cityhash<_Size, 64> return __b; } - static _Size __hash_len_0_to_16(const char* __s, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_0_to_16(const char* __s, _Size __len) { if (__len > 8) { const _Size __a = std::__loadword<_Size>(__s); const _Size __b = std::__loadword<_Size>(__s + __len - 8); @@ -158,9 +197,8 @@ struct __murmur2_or_cityhash<_Size, 64> return __k2; } - static _Size __hash_len_17_to_32(const char *__s, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_17_to_32(const char *__s, _Size __len) { const _Size __a = std::__loadword<_Size>(__s) * __k1; const _Size __b = std::__loadword<_Size>(__s + 8); const _Size __c = std::__loadword<_Size>(__s + __len - 8) * __k2; @@ -171,9 +209,9 @@ struct __murmur2_or_cityhash<_Size, 64> // Return a 16-byte hash for 48 bytes. Quick and dirty. // Callers do best to use "random-looking" values for a and b. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static pair<_Size, _Size> __weak_hash_len_32_with_seeds( _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { __a += __w; __b = __rotate(__b + __a + __z, 21); @@ -185,9 +223,9 @@ struct __murmur2_or_cityhash<_Size, 64> } // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static pair<_Size, _Size> __weak_hash_len_32_with_seeds( const char* __s, _Size __a, _Size __b) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { return __weak_hash_len_32_with_seeds(std::__loadword<_Size>(__s), std::__loadword<_Size>(__s + 8), @@ -198,9 +236,8 @@ struct __murmur2_or_cityhash<_Size, 64> } // Return an 8-byte hash for 33 to 64 bytes. - static _Size __hash_len_33_to_64(const char *__s, size_t __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_33_to_64(const char *__s, size_t __len) { _Size __z = std::__loadword<_Size>(__s + 24); _Size __a = std::__loadword<_Size>(__s) + (__len + std::__loadword<_Size>(__s + __len - 16)) * __k0; @@ -225,53 +262,6 @@ struct __murmur2_or_cityhash<_Size, 64> } }; -// cityhash64 -template -_Size -__murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) -{ - const char* __s = static_cast(__key); - if (__len <= 32) { - if (__len <= 16) { - return __hash_len_0_to_16(__s, __len); - } else { - return __hash_len_17_to_32(__s, __len); - } - } else if (__len <= 64) { - return __hash_len_33_to_64(__s, __len); - } - - // For strings over 64 bytes we hash the end first, and then as we - // loop we keep 56 bytes of state: v, w, x, y, and z. - _Size __x = std::__loadword<_Size>(__s + __len - 40); - _Size __y = std::__loadword<_Size>(__s + __len - 16) + - std::__loadword<_Size>(__s + __len - 56); - _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, - std::__loadword<_Size>(__s + __len - 24)); - pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); - pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); - __x = __x * __k1 + std::__loadword<_Size>(__s); - - // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - __len = (__len - 1) & ~static_cast<_Size>(63); - do { - __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; - __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; - __x ^= __w.second; - __y += __v.first + std::__loadword<_Size>(__s + 40); - __z = __rotate(__z + __w.first, 33) * __k1; - __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); - __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, - __y + std::__loadword<_Size>(__s + 16)); - _VSTD::swap(__z, __x); - __s += 64; - __len -= 64; - } while (__len != 0); - return __hash_len_16( - __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, - __hash_len_16(__v.second, __w.second) + __x); -} - template struct __scalar_hash; @@ -279,7 +269,7 @@ template struct __scalar_hash<_Tp, 0> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -297,7 +287,7 @@ template struct __scalar_hash<_Tp, 1> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -314,7 +304,7 @@ template struct __scalar_hash<_Tp, 2> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -335,7 +325,7 @@ template struct __scalar_hash<_Tp, 3> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -357,7 +347,7 @@ template struct __scalar_hash<_Tp, 4> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -381,7 +371,7 @@ struct _PairT { size_t second; }; -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_HIDE_FROM_ABI inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT { typedef __scalar_hash<_PairT> _HashT; const _PairT __p = {__lhs, __rhs}; @@ -392,7 +382,7 @@ template struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> : public __unary_function<_Tp*, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp* __v) const _NOEXCEPT { union @@ -409,7 +399,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -417,7 +407,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -425,7 +415,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -433,7 +423,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -442,7 +432,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT {return static_cast(__v);} }; #endif // !_LIBCPP_HAS_NO_CHAR8_T @@ -451,7 +441,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -459,7 +449,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -468,7 +458,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast(__v);} }; #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -477,7 +467,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -485,7 +475,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -493,7 +483,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -501,7 +491,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -509,7 +499,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -517,7 +507,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT {return static_cast(__v);} }; @@ -553,7 +543,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -567,7 +557,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -581,7 +571,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -631,7 +621,7 @@ template ::value> struct _LIBCPP_TEMPLATE_VIS __enum_hash : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { typedef typename underlying_type<_Tp>::type type; @@ -650,13 +640,13 @@ struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> { }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(nullptr_t) const _NOEXCEPT { return 662607004ull; } @@ -677,7 +667,7 @@ using __has_enabled_hash _LIBCPP_NODEBUG = integral_constant::value >; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template using __enable_hash_helper_imp _LIBCPP_NODEBUG = _Type; diff --git a/lib/libcxx/include/__functional/identity.h b/lib/libcxx/include/__functional/identity.h index 2fe3acca08..5dffedf677 100644 --- a/lib/libcxx/include/__functional/identity.h +++ b/lib/libcxx/include/__functional/identity.h @@ -11,6 +11,7 @@ #define _LIBCPP___FUNCTIONAL_IDENTITY_H #include <__config> +#include <__type_traits/integral_constant.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -19,27 +20,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template +struct __is_identity : false_type {}; + struct __identity { template - _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR _Tp&& operator()(_Tp&& __t) const _NOEXCEPT { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp&& operator()(_Tp&& __t) const _NOEXCEPT { return std::forward<_Tp>(__t); } using is_transparent = void; }; -#if _LIBCPP_STD_VER > 17 +template <> +struct __is_identity<__identity> : true_type {}; + +#if _LIBCPP_STD_VER >= 20 struct identity { template - _LIBCPP_NODISCARD_EXT constexpr _Tp&& operator()(_Tp&& __t) const noexcept + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { return _VSTD::forward<_Tp>(__t); } using is_transparent = void; }; -#endif // _LIBCPP_STD_VER > 17 + +template <> +struct __is_identity : true_type {}; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/invoke.h b/lib/libcxx/include/__functional/invoke.h index 48e6eac3ce..a7dd311074 100644 --- a/lib/libcxx/include/__functional/invoke.h +++ b/lib/libcxx/include/__functional/invoke.h @@ -11,525 +11,16 @@ #define _LIBCPP___FUNCTIONAL_INVOKE_H #include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/apply_cv.h> -#include <__type_traits/conditional.h> -#include <__type_traits/decay.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/integral_constant.h> -#include <__type_traits/is_base_of.h> -#include <__type_traits/is_core_convertible.h> -#include <__type_traits/is_member_function_pointer.h> -#include <__type_traits/is_member_object_pointer.h> -#include <__type_traits/is_reference_wrapper.h> -#include <__type_traits/is_same.h> -#include <__type_traits/is_void.h> -#include <__type_traits/nat.h> -#include <__type_traits/remove_cv.h> -#include <__utility/declval.h> +#include <__type_traits/invoke.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -// TODO: Disentangle the type traits and std::invoke properly - _LIBCPP_BEGIN_NAMESPACE_STD -struct __any -{ - __any(...); -}; - -template -struct __member_pointer_traits_imp -{ -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> -{ - typedef _Class const _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> -{ - typedef _Class const _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> -{ - typedef _Class volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> -{ - typedef _Class volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> -{ - typedef _Class const volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> -{ - typedef _Class const volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &, true, false> -{ - typedef _Class& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &, true, false> -{ - typedef _Class& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> -{ - typedef _Class const& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> -{ - typedef _Class const& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> -{ - typedef _Class volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> -{ - typedef _Class volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> -{ - typedef _Class const volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> -{ - typedef _Class const volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &&, true, false> -{ - typedef _Class&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &&, true, false> -{ - typedef _Class&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> -{ - typedef _Class const&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> -{ - typedef _Class const&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> -{ - typedef _Class volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> -{ - typedef _Class volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> -{ - typedef _Class const volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> -{ - typedef _Class const volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template -struct __member_pointer_traits_imp<_Rp _Class::*, false, true> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; -}; - -template -struct __member_pointer_traits - : public __member_pointer_traits_imp<__remove_cv_t<_MP>, - is_member_function_pointer<_MP>::value, - is_member_object_pointer<_MP>::value> -{ -// typedef ... _ClassType; -// typedef ... _ReturnType; -// typedef ... _FnType; -}; - -template -struct __member_pointer_class_type {}; - -template -struct __member_pointer_class_type<_Ret _ClassType::*> { - typedef _ClassType type; -}; - -template ::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet1 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && is_base_of<_ClassT, _DecayA0>::value - >::type; - -template ::type, - class _DecayA0 = typename decay<_A0>::type> -using __enable_if_bullet2 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && __is_reference_wrapper<_DecayA0>::value - >::type; - -template ::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet3 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && !is_base_of<_ClassT, _DecayA0>::value - && !__is_reference_wrapper<_DecayA0>::value - >::type; - -template ::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet4 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && is_base_of<_ClassT, _DecayA0>::value - >::type; - -template ::type, - class _DecayA0 = typename decay<_A0>::type> -using __enable_if_bullet5 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && __is_reference_wrapper<_DecayA0>::value - >::type; - -template ::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet6 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && !is_base_of<_ClassT, _DecayA0>::value - && !__is_reference_wrapper<_DecayA0>::value - >::type; - -// __invoke forward declarations - -// fall back - none of the bullets - -template -__nat __invoke(__any, _Args&& ...__args); - -// bullets 1, 2 and 3 - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) - { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) - { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) - { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } - -// bullets 4, 5 and 6 - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) - { return static_cast<_A0&&>(__a0).*__f; } - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().get().*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept(__a0.get().*__f)) - { return __a0.get().*__f; } - -template > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((*std::declval<_A0>()).*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) - { return (*static_cast<_A0&&>(__a0)).*__f; } - -// bullet 7 - -template -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_Fp>()(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _Args&& ...__args) - _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) - { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } - -// __invokable -template -struct __invokable_r -{ - template - static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); - template - static __nat __try_call(...); - - // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, - // or incomplete array types as required by the standard. - using _Result = decltype(__try_call<_Fp, _Args...>(0)); - - using type = __conditional_t< - _IsNotSame<_Result, __nat>::value, - __conditional_t::value, true_type, __is_core_convertible<_Result, _Ret> >, - false_type>; - static const bool value = type::value; -}; -template -using __invokable = __invokable_r; - -template -struct __nothrow_invokable_r_imp { - static const bool value = false; -}; - -template -struct __nothrow_invokable_r_imp -{ - typedef __nothrow_invokable_r_imp _ThisT; - - template - static void __test_noexcept(_Tp) _NOEXCEPT; - -#ifdef _LIBCPP_CXX03_LANG - static const bool value = false; -#else - static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( - _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); -#endif -}; - -template -struct __nothrow_invokable_r_imp -{ -#ifdef _LIBCPP_CXX03_LANG - static const bool value = false; -#else - static const bool value = noexcept( - _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); -#endif -}; - -template -using __nothrow_invokable_r = - __nothrow_invokable_r_imp< - __invokable_r<_Ret, _Fp, _Args...>::value, - is_void<_Ret>::value, - _Ret, _Fp, _Args... - >; - -template -using __nothrow_invokable = - __nothrow_invokable_r_imp< - __invokable<_Fp, _Args...>::value, - true, void, _Fp, _Args... - >; - -template -struct __invoke_of - : public enable_if< - __invokable<_Fp, _Args...>::value, - typename __invokable_r::_Result> -{ -}; - -template ::value> -struct __invoke_void_return_wrapper -{ - template - static _Ret __call(_Args&&... __args) { - return std::__invoke(std::forward<_Args>(__args)...); - } -}; - -template -struct __invoke_void_return_wrapper<_Ret, true> -{ - template - static void __call(_Args&&... __args) { - std::__invoke(std::forward<_Args>(__args)...); - } -}; - -#if _LIBCPP_STD_VER > 14 - -// is_invocable - -template -struct _LIBCPP_TEMPLATE_VIS is_invocable - : integral_constant::value> {}; - -template -struct _LIBCPP_TEMPLATE_VIS is_invocable_r - : integral_constant::value> {}; - -template -inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; - -template -inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; - -// is_nothrow_invocable - -template -struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable - : integral_constant::value> {}; - -template -struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r - : integral_constant::value> {}; - -template -inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; - -template -inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; - -template -struct _LIBCPP_TEMPLATE_VIS invoke_result - : __invoke_of<_Fn, _Args...> -{ -}; - -template -using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 invoke_result_t<_Fn, _Args...> @@ -539,7 +30,26 @@ invoke(_Fn&& __f, _Args&&... __args) return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 + +#if _LIBCPP_STD_VER >= 23 +template + requires is_invocable_r_v<_Result, _Fn, _Args...> +_LIBCPP_HIDE_FROM_ABI constexpr _Result +invoke_r(_Fn&& __f, _Args&&... __args) noexcept(is_nothrow_invocable_r_v<_Result, _Fn, _Args...>) { + if constexpr (is_void_v<_Result>) { + static_cast(std::invoke(std::forward<_Fn>(__f), std::forward<_Args>(__args)...)); + } else { + // TODO: Use reference_converts_from_temporary_v once implemented + // using _ImplicitInvokeResult = invoke_result_t<_Fn, _Args...>; + // static_assert(!reference_converts_from_temporary_v<_Result, _ImplicitInvokeResult>, + static_assert(true, + "Returning from invoke_r would bind a temporary object to the reference return type, " + "which would result in a dangling reference."); + return std::invoke(std::forward<_Fn>(__f), std::forward<_Args>(__args)...); + } +} +#endif _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/is_transparent.h b/lib/libcxx/include/__functional/is_transparent.h index c7a0ee9ee7..c539a07d69 100644 --- a/lib/libcxx/include/__functional/is_transparent.h +++ b/lib/libcxx/include/__functional/is_transparent.h @@ -11,7 +11,8 @@ #define _LIBCPP___FUNCTIONAL_IS_TRANSPARENT #include <__config> -#include +#include <__type_traits/integral_constant.h> +#include <__type_traits/void_t.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template struct __is_transparent : false_type {}; diff --git a/lib/libcxx/include/__functional/mem_fn.h b/lib/libcxx/include/__functional/mem_fn.h index 8b51627079..fe221dd128 100644 --- a/lib/libcxx/include/__functional/mem_fn.h +++ b/lib/libcxx/include/__functional/mem_fn.h @@ -15,7 +15,6 @@ #include <__functional/invoke.h> #include <__functional/weak_result_type.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__functional/not_fn.h b/lib/libcxx/include/__functional/not_fn.h index 79d9a8710b..0cdb1b7e23 100644 --- a/lib/libcxx/include/__functional/not_fn.h +++ b/lib/libcxx/include/__functional/not_fn.h @@ -13,8 +13,11 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 struct __not_fn_op { template @@ -47,7 +50,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 auto not_fn(_Fn&& __f) { return __not_fn_t>(_VSTD::forward<_Fn>(__f)); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/operations.h b/lib/libcxx/include/__functional/operations.h index 8a781efbdb..6cdb89d6b4 100644 --- a/lib/libcxx/include/__functional/operations.h +++ b/lib/libcxx/include/__functional/operations.h @@ -13,6 +13,9 @@ #include <__config> #include <__functional/binary_function.h> #include <__functional/unary_function.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/operation_traits.h> +#include <__type_traits/predicate_traits.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Arithmetic operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -38,7 +41,15 @@ struct _LIBCPP_TEMPLATE_VIS plus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus); -#if _LIBCPP_STD_VER > 11 +template +struct __is_trivial_plus_operation, _Tp, _Tp> : true_type {}; + +#if _LIBCPP_STD_VER >= 14 +template +struct __is_trivial_plus_operation, _Tp, _Up> : true_type {}; +#endif + +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS plus { @@ -52,7 +63,7 @@ struct _LIBCPP_TEMPLATE_VIS plus }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -67,7 +78,7 @@ struct _LIBCPP_TEMPLATE_VIS minus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(minus); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS minus { @@ -81,7 +92,7 @@ struct _LIBCPP_TEMPLATE_VIS minus }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -96,7 +107,7 @@ struct _LIBCPP_TEMPLATE_VIS multiplies }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(multiplies); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS multiplies { @@ -110,7 +121,7 @@ struct _LIBCPP_TEMPLATE_VIS multiplies }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -125,7 +136,7 @@ struct _LIBCPP_TEMPLATE_VIS divides }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(divides); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS divides { @@ -139,7 +150,7 @@ struct _LIBCPP_TEMPLATE_VIS divides }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -154,7 +165,7 @@ struct _LIBCPP_TEMPLATE_VIS modulus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(modulus); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS modulus { @@ -168,7 +179,7 @@ struct _LIBCPP_TEMPLATE_VIS modulus }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -183,7 +194,7 @@ struct _LIBCPP_TEMPLATE_VIS negate }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(negate); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS negate { @@ -199,7 +210,7 @@ struct _LIBCPP_TEMPLATE_VIS negate // Bitwise operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -214,7 +225,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_and }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_and); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_and { @@ -228,7 +239,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_and }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template struct _LIBCPP_TEMPLATE_VIS bit_not : __unary_function<_Tp, _Tp> @@ -252,7 +263,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_not }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -267,7 +278,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_or }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_or); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_or { @@ -281,7 +292,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_or }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -296,7 +307,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_xor); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_xor { @@ -312,7 +323,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor // Comparison operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -327,7 +338,7 @@ struct _LIBCPP_TEMPLATE_VIS equal_to }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(equal_to); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS equal_to { @@ -341,7 +352,15 @@ struct _LIBCPP_TEMPLATE_VIS equal_to }; #endif -#if _LIBCPP_STD_VER > 11 +template +struct __is_trivial_equality_predicate, _Tp, _Tp> : true_type {}; + +#if _LIBCPP_STD_VER >= 14 +template +struct __is_trivial_equality_predicate, _Tp, _Tp> : true_type {}; +#endif + +#if _LIBCPP_STD_VER >= 14 template #else template @@ -356,7 +375,7 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(not_equal_to); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS not_equal_to { @@ -370,7 +389,7 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -385,7 +404,7 @@ struct _LIBCPP_TEMPLATE_VIS less }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS less { @@ -399,7 +418,7 @@ struct _LIBCPP_TEMPLATE_VIS less }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -414,7 +433,7 @@ struct _LIBCPP_TEMPLATE_VIS less_equal }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less_equal); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS less_equal { @@ -428,7 +447,7 @@ struct _LIBCPP_TEMPLATE_VIS less_equal }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -443,7 +462,7 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater_equal); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS greater_equal { @@ -457,7 +476,7 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -472,7 +491,7 @@ struct _LIBCPP_TEMPLATE_VIS greater }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS greater { @@ -488,7 +507,7 @@ struct _LIBCPP_TEMPLATE_VIS greater // Logical operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -503,7 +522,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_and }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_and); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_and { @@ -517,7 +536,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_and }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -532,7 +551,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_not }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_not); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_not { @@ -546,7 +565,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_not }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template #else template @@ -561,7 +580,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_or }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_or); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_or { diff --git a/lib/libcxx/include/__functional/perfect_forward.h b/lib/libcxx/include/__functional/perfect_forward.h index 9ffea1a8c7..b848fbf696 100644 --- a/lib/libcxx/include/__functional/perfect_forward.h +++ b/lib/libcxx/include/__functional/perfect_forward.h @@ -11,19 +11,25 @@ #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H #include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constructible.h> #include <__utility/declval.h> #include <__utility/forward.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include -#include #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 > 14 +#if _LIBCPP_STD_VER >= 17 template struct __perfect_forward_impl; @@ -37,14 +43,14 @@ public: template , _Args&&...> >> - explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) + _LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) : __bound_args_(_VSTD::forward<_Args>(__bound_args)...) {} - __perfect_forward_impl(__perfect_forward_impl const&) = default; - __perfect_forward_impl(__perfect_forward_impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl&&) = default; - __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; - __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; template >> _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & @@ -87,8 +93,10 @@ public: template using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H diff --git a/lib/libcxx/include/__functional/ranges_operations.h b/lib/libcxx/include/__functional/ranges_operations.h index 87081dd56a..c344fc38f9 100644 --- a/lib/libcxx/include/__functional/ranges_operations.h +++ b/lib/libcxx/include/__functional/ranges_operations.h @@ -13,6 +13,8 @@ #include <__concepts/equality_comparable.h> #include <__concepts/totally_ordered.h> #include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/predicate_traits.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -21,14 +23,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { struct equal_to { template requires equality_comparable_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)))) { return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u); } @@ -39,7 +41,7 @@ struct equal_to { struct not_equal_to { template requires equality_comparable_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u))))) { return !(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)); } @@ -50,7 +52,7 @@ struct not_equal_to { struct less { template requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)))) { return _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u); } @@ -61,7 +63,7 @@ struct less { struct less_equal { template requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t))))) { return !(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)); } @@ -72,7 +74,7 @@ struct less_equal { struct greater { template requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)))) { return _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t); } @@ -83,7 +85,7 @@ struct greater { struct greater_equal { template requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u))))) { return !(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)); } @@ -93,7 +95,10 @@ struct greater_equal { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +template +struct __is_trivial_equality_predicate : true_type {}; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/reference_wrapper.h b/lib/libcxx/include/__functional/reference_wrapper.h index c377b64377..2d382a34f6 100644 --- a/lib/libcxx/include/__functional/reference_wrapper.h +++ b/lib/libcxx/include/__functional/reference_wrapper.h @@ -55,12 +55,18 @@ public: template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of::type - operator() (_ArgTypes&&... __args) const { + operator() (_ArgTypes&&... __args) const +#if _LIBCPP_STD_VER >= 17 + // Since is_nothrow_invocable requires C++17 LWG3764 is not backported + // to earlier versions. + noexcept(is_nothrow_invocable_v<_Tp&, _ArgTypes...>) +#endif + { return std::__invoke(get(), std::forward<_ArgTypes>(__args)...); } }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; #endif diff --git a/lib/libcxx/include/__fwd/fstream.h b/lib/libcxx/include/__fwd/fstream.h new file mode 100644 index 0000000000..b4a112bfd4 --- /dev/null +++ b/lib/libcxx/include/__fwd/fstream.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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_FSTREAM_H +#define _LIBCPP___FWD_FSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_filebuf; +template > +class _LIBCPP_TEMPLATE_VIS basic_ifstream; +template > +class _LIBCPP_TEMPLATE_VIS basic_ofstream; +template > +class _LIBCPP_TEMPLATE_VIS basic_fstream; + +using filebuf = basic_filebuf; +using ifstream = basic_ifstream; +using ofstream = basic_ofstream; +using fstream = basic_fstream; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wfilebuf = basic_filebuf; +using wifstream = basic_ifstream; +using wofstream = basic_ofstream; +using wfstream = basic_fstream; +#endif + +template +class _LIBCPP_PREFERRED_NAME(filebuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfilebuf)) basic_filebuf; +template +class _LIBCPP_PREFERRED_NAME(ifstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wifstream)) basic_ifstream; +template +class _LIBCPP_PREFERRED_NAME(ofstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wofstream)) basic_ofstream; +template +class _LIBCPP_PREFERRED_NAME(fstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfstream)) basic_fstream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_FSTREAM_H diff --git a/lib/libcxx/include/__fwd/get.h b/lib/libcxx/include/__fwd/get.h index ec1fab4602..d04341496c 100644 --- a/lib/libcxx/include/__fwd/get.h +++ b/lib/libcxx/include/__fwd/get.h @@ -15,7 +15,7 @@ #include <__fwd/pair.h> #include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_element.h> +#include <__tuple/tuple_element.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/lib/libcxx/include/__fwd/ios.h b/lib/libcxx/include/__fwd/ios.h new file mode 100644 index 0000000000..82c865d58c --- /dev/null +++ b/lib/libcxx/include/__fwd/ios.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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_IOS_H +#define _LIBCPP___FWD_IOS_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_ios; + +using ios = basic_ios; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wios = basic_ios; +#endif + +template +class _LIBCPP_PREFERRED_NAME(ios) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wios)) basic_ios; + +#if defined(_NEWLIB_VERSION) +// On newlib, off_t is 'long int' +using streamoff = long int; // for char_traits in +#else +using streamoff = long long; // for char_traits in +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_IOS_H diff --git a/lib/libcxx/include/__fwd/istream.h b/lib/libcxx/include/__fwd/istream.h new file mode 100644 index 0000000000..a06907a6c8 --- /dev/null +++ b/lib/libcxx/include/__fwd/istream.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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_ISTREAM_H +#define _LIBCPP___FWD_ISTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_istream; + +template > +class _LIBCPP_TEMPLATE_VIS basic_iostream; + +using istream = basic_istream; +using iostream = basic_iostream; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wistream = basic_istream; +using wiostream = basic_iostream; +#endif + +template +class _LIBCPP_PREFERRED_NAME(istream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistream)) basic_istream; + +template +class _LIBCPP_PREFERRED_NAME(iostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wiostream)) basic_iostream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_ISTREAM_H diff --git a/lib/libcxx/include/__fwd/mdspan.h b/lib/libcxx/include/__fwd/mdspan.h new file mode 100644 index 0000000000..a3628c2d60 --- /dev/null +++ b/lib/libcxx/include/__fwd/mdspan.h @@ -0,0 +1,60 @@ +// -*- 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_LAYOUTS_H +#define _LIBCPP___MDSPAN_LAYOUTS_H + +#include <__config> + +#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 + +// Layout policy with a mapping which corresponds to FORTRAN-style array layouts +struct layout_left { + template + class mapping; +}; + +// Layout policy with a mapping which corresponds to C-style array layouts +struct layout_right { + template + class mapping; +}; + +/* +// Will be implemented with follow on revision +// Layout policy with a unique mapping where strides are arbitrary +struct layout_stride { + template + class mapping; +}; +*/ + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUTS_H diff --git a/lib/libcxx/include/__fwd/memory_resource.h b/lib/libcxx/include/__fwd/memory_resource.h index 718a9078d3..03b78ad2bd 100644 --- a/lib/libcxx/include/__fwd/memory_resource.h +++ b/lib/libcxx/include/__fwd/memory_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___FWD_MEMORY_RESOURCE_H #define _LIBCPP___FWD_MEMORY_RESOURCE_H +#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -19,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template -class _LIBCPP_TEMPLATE_VIS polymorphic_allocator; +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator; } // namespace pmr _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__fwd/ostream.h b/lib/libcxx/include/__fwd/ostream.h new file mode 100644 index 0000000000..3347e0f71d --- /dev/null +++ b/lib/libcxx/include/__fwd/ostream.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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_OSTREAM_H +#define _LIBCPP___FWD_OSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_ostream; + +using ostream = basic_ostream; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wostream = basic_ostream; +#endif + +template +class _LIBCPP_PREFERRED_NAME(ostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostream)) basic_ostream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_OSTREAM_H diff --git a/lib/libcxx/include/__fwd/span.h b/lib/libcxx/include/__fwd/span.h index 943cb13fa1..e9fa70382f 100644 --- a/lib/libcxx/include/__fwd/span.h +++ b/lib/libcxx/include/__fwd/span.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 inline constexpr size_t dynamic_extent = numeric_limits::max(); template class span; diff --git a/lib/libcxx/include/__fwd/sstream.h b/lib/libcxx/include/__fwd/sstream.h new file mode 100644 index 0000000000..e2d46fbe1d --- /dev/null +++ b/lib/libcxx/include/__fwd/sstream.h @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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_SSTREAM_H +#define _LIBCPP___FWD_SSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_stringbuf; + +template , class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_istringstream; +template , class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ostringstream; +template , class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_stringstream; + +using stringbuf = basic_stringbuf; +using istringstream = basic_istringstream; +using ostringstream = basic_ostringstream; +using stringstream = basic_stringstream; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstringbuf = basic_stringbuf; +using wistringstream = basic_istringstream; +using wostringstream = basic_ostringstream; +using wstringstream = basic_stringstream; +#endif + +template +class _LIBCPP_PREFERRED_NAME(stringbuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringbuf)) basic_stringbuf; +template +class _LIBCPP_PREFERRED_NAME(istringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistringstream)) basic_istringstream; +template +class _LIBCPP_PREFERRED_NAME(ostringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostringstream)) basic_ostringstream; +template +class _LIBCPP_PREFERRED_NAME(stringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringstream)) basic_stringstream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_SSTREAM_H diff --git a/lib/libcxx/include/__fwd/streambuf.h b/lib/libcxx/include/__fwd/streambuf.h new file mode 100644 index 0000000000..b35afa6afe --- /dev/null +++ b/lib/libcxx/include/__fwd/streambuf.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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_STREAMBUF_H +#define _LIBCPP___FWD_STREAMBUF_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_TEMPLATE_VIS basic_streambuf; + +using streambuf = basic_streambuf; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstreambuf = basic_streambuf; +#endif + +template +class _LIBCPP_PREFERRED_NAME(streambuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstreambuf)) basic_streambuf; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_STREAMBUF_H diff --git a/lib/libcxx/include/__fwd/string.h b/lib/libcxx/include/__fwd/string.h index 7ab5561b75..032132374d 100644 --- a/lib/libcxx/include/__fwd/string.h +++ b/lib/libcxx/include/__fwd/string.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___FWD_STRING_H #define _LIBCPP___FWD_STRING_H +#include <__availability> #include <__config> #include <__fwd/memory_resource.h> @@ -61,21 +62,20 @@ using u32string = basic_string; namespace pmr { template > -using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; +using basic_string _LIBCPP_AVAILABILITY_PMR = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; -using string = basic_string; +using string _LIBCPP_AVAILABILITY_PMR = basic_string; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -using wstring = basic_string; +using wstring _LIBCPP_AVAILABILITY_PMR = basic_string; # endif # ifndef _LIBCPP_HAS_NO_CHAR8_T -using u8string = basic_string; +using u8string _LIBCPP_AVAILABILITY_PMR = basic_string; # endif -using u16string = basic_string; -using u32string = basic_string; - +using u16string _LIBCPP_AVAILABILITY_PMR = basic_string; +using u32string _LIBCPP_AVAILABILITY_PMR = basic_string; } // namespace pmr #endif // _LIBCPP_STD_VER >= 17 diff --git a/lib/libcxx/include/__hash_table b/lib/libcxx/include/__hash_table index f8896c8664..2ae7afdc10 100644 --- a/lib/libcxx/include/__hash_table +++ b/lib/libcxx/include/__hash_table @@ -15,8 +15,8 @@ #include <__assert> #include <__bit/countl.h> #include <__config> -#include <__debug> #include <__functional/hash.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/allocator_traits.h> @@ -25,6 +25,19 @@ #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -32,7 +45,6 @@ #include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -59,8 +71,7 @@ struct __is_hash_value_type : false_type {}; template struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {}; -_LIBCPP_FUNC_VIS -size_t __next_prime(size_t __n); +_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n); template struct __hash_node_base @@ -296,53 +307,20 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_iterator(const __hash_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_iterator& operator=(const __hash_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container iterator"); __node_ = __node_->__next_; return *this; } @@ -366,14 +344,11 @@ public: private: _LIBCPP_INLINE_VISIBILITY - explicit __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + explicit __hash_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } + template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; @@ -402,61 +377,25 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); -#endif } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator(const __hash_const_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator& operator=(const __hash_const_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container const_iterator"); __node_ = __node_->__next_; return *this; } @@ -480,14 +419,11 @@ public: private: _LIBCPP_INLINE_VISIBILITY - explicit __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + explicit __hash_const_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } + template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS unordered_map; @@ -513,57 +449,20 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator(const __hash_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_local_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator& operator=(const __hash_local_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -590,18 +489,15 @@ public: private: _LIBCPP_INLINE_VISIBILITY explicit __hash_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT + size_t __bucket_count) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif if (__node_ != nullptr) __node_ = __node_->__next_; } + template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; @@ -635,7 +531,6 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY @@ -644,59 +539,20 @@ public: __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); -#endif } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator(const __hash_const_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_local_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container const_local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -723,18 +579,15 @@ public: private: _LIBCPP_INLINE_VISIBILITY explicit __hash_const_local_iterator(__next_pointer __node_ptr, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT + size_t __bucket_count) _NOEXCEPT : __node_(__node_ptr), __bucket_(__bucket), __bucket_count_(__bucket_count) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif if (__node_ != nullptr) __node_ = __node_->__next_; } + template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; }; @@ -803,8 +656,8 @@ private: public: bool __value_constructed; - __hash_node_destructor(__hash_node_destructor const&) = default; - __hash_node_destructor& operator=(const __hash_node_destructor&) = delete; + _LIBCPP_HIDE_FROM_ABI __hash_node_destructor(__hash_node_destructor const&) = default; + _LIBCPP_HIDE_FROM_ABI __hash_node_destructor& operator=(const __hash_node_destructor&) = delete; _LIBCPP_INLINE_VISIBILITY @@ -826,7 +679,7 @@ public: template friend class __hash_map_node_destructor; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template struct __generic_container_node_destructor; @@ -976,22 +829,22 @@ public: is_nothrow_default_constructible::value); _LIBCPP_INLINE_VISIBILITY __hash_table(const hasher& __hf, const key_equal& __eql); - __hash_table(const hasher& __hf, const key_equal& __eql, + _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - explicit __hash_table(const allocator_type& __a); - __hash_table(const __hash_table& __u); - __hash_table(const __hash_table& __u, const allocator_type& __a); - __hash_table(__hash_table&& __u) + _LIBCPP_HIDE_FROM_ABI explicit __hash_table(const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u); + _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u) _NOEXCEPT_( is_nothrow_move_constructible<__bucket_list>::value && is_nothrow_move_constructible<__first_node>::value && is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); - __hash_table(__hash_table&& __u, const allocator_type& __a); - ~__hash_table(); + _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI ~__hash_table(); - __hash_table& operator=(const __hash_table& __u); + _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u); _LIBCPP_INLINE_VISIBILITY __hash_table& operator=(__hash_table&& __u) _NOEXCEPT_( @@ -1000,9 +853,9 @@ public: is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); template - void __assign_unique(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last); template - void __assign_multi(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last); _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT @@ -1121,7 +974,7 @@ public: return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh); @@ -1151,7 +1004,7 @@ public: _NodeHandle __node_handle_extract(const_iterator __it); #endif - void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY void __rehash_unique(size_type __n) { __rehash(__n); } _LIBCPP_INLINE_VISIBILITY void __rehash_multi(size_type __n) { __rehash(__n); } _LIBCPP_INLINE_VISIBILITY void __reserve_unique(size_type __n) @@ -1182,48 +1035,48 @@ public: _LIBCPP_INLINE_VISIBILITY size_type bucket(const _Key& __k) const { - _LIBCPP_ASSERT(bucket_count() > 0, + _LIBCPP_ASSERT_UNCATEGORIZED(bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0"); return std::__constrain_hash(hash_function()(__k), bucket_count()); } template - iterator find(const _Key& __x); + _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __x); template - const_iterator find(const _Key& __x) const; + _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __x) const; typedef __hash_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; - iterator erase(const_iterator __p); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last); template - size_type __erase_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k); template - size_type __erase_multi(const _Key& __k); - __node_holder remove(const_iterator __p) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY size_type __count_unique(const _Key& __k) const; template - size_type __count_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const; template - pair + _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k); template - pair + _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k) const; template - pair + _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k); template - pair + _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k) const; - void swap(__hash_table& __u) + _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_( __is_nothrow_swappable::value && __is_nothrow_swappable::value @@ -1239,7 +1092,7 @@ public: _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT {return max_size(); } - size_type bucket_size(size_type __n) const; + _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const; _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT { size_type __bc = bucket_count(); @@ -1247,7 +1100,7 @@ public: } _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT { - _LIBCPP_ASSERT(__mlf > 0, + _LIBCPP_ASSERT_UNCATEGORIZED(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0"); max_load_factor() = _VSTD::max(__mlf, load_factor()); } @@ -1256,68 +1109,61 @@ public: local_iterator begin(size_type __n) { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()"); - return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + return local_iterator(__bucket_list_[__n], __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n) { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()"); - return local_iterator(nullptr, __n, bucket_count(), this); + return local_iterator(nullptr, __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()"); - return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()"); - return const_local_iterator(nullptr, __n, bucket_count(), this); + return const_local_iterator(nullptr, __n, bucket_count()); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const; - bool __decrementable(const const_iterator* __i) const; - bool __addable(const const_iterator* __i, ptrdiff_t __n) const; - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - private: - template void __rehash(size_type __n); - template void __do_rehash(size_type __n); + template + _LIBCPP_HIDE_FROM_ABI void __rehash(size_type __n); + template + _LIBCPP_HIDE_FROM_ABI void __do_rehash(size_type __n); template - __node_holder __construct_node(_Args&& ...__args); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&& ...__args); template - __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table& __u) {__copy_assign_alloc(__u, integral_constant());} - void __copy_assign_alloc(const __hash_table& __u, true_type); + _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u, true_type); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table&, false_type) {} - void __move_assign(__hash_table& __u, false_type); - void __move_assign(__hash_table& __u, true_type) + _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, false_type); + _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, true_type) _NOEXCEPT_( is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable::value && @@ -1343,8 +1189,8 @@ private: _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} - void __deallocate_node(__next_pointer __np) _NOEXCEPT; - __next_pointer __detach() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; @@ -1476,7 +1322,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() #endif __deallocate_node(__p1_.first().__next_); - std::__debug_db_erase_c(this); } template @@ -1518,21 +1363,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) while (__np != nullptr) { __next_pointer __next = __np->__next_; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast((*__p)->__i_); - if (__i->__node_ == __np) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __real_np = __np->__upcast(); __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_)); __node_traits::deallocate(__na, __real_np, 1); @@ -1579,7 +1409,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } - std::__debug_db_swap(this, std::addressof(__u)); } template @@ -1597,10 +1426,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { @@ -1610,14 +1439,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __node_insert_multi(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } const_iterator __i = __u.begin(); @@ -1659,10 +1488,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__upcast()->__value_ = *__first; @@ -1670,14 +1499,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first __node_insert_unique(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } for (; __first != __last; ++__first) @@ -1699,10 +1528,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__upcast()->__value_ = *__first; @@ -1710,14 +1539,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, __node_insert_multi(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } for (; __first != __last; ++__first) @@ -1729,7 +1558,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT { - return iterator(__p1_.first().__next_, this); + return iterator(__p1_.first().__next_); } template @@ -1737,7 +1566,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT { - return iterator(nullptr, this); + return iterator(nullptr); } template @@ -1745,7 +1574,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT { - return const_iterator(__p1_.first().__next_, this); + return const_iterator(__p1_.first().__next_); } template @@ -1753,7 +1582,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT { - return const_iterator(nullptr, this); + return const_iterator(nullptr); } template @@ -1794,10 +1623,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare( if (__ndptr != nullptr) { for (__ndptr = __ndptr->__next_; __ndptr != nullptr && - std::__constrain_hash(__ndptr->__hash(), __bc) == __chash; + (__ndptr->__hash() == __hash || + std::__constrain_hash(__ndptr->__hash(), __bc) == __chash); __ndptr = __ndptr->__next_) { - if (key_eq()(__ndptr->__upcast()->__value_, __value)) + if ((__ndptr->__hash() == __hash) && + key_eq()(__ndptr->__upcast()->__value_, __value)) return __ndptr; } } @@ -1858,7 +1689,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __ __existing_node = __nd->__ptr(); __inserted = true; } - return pair(iterator(__existing_node, this), __inserted); + return pair(iterator(__existing_node), __inserted); } // Prepare the container for an insertion of the value __cp_val with the hash @@ -1952,7 +1783,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_); __node_insert_multi_perform(__cp, __pn); - return iterator(__cp->__ptr(), this); + return iterator(__cp->__ptr()); } template @@ -1960,9 +1791,6 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( const_iterator __p, __node_pointer __cp) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); if (__p != end() && key_eq()(*__p, __cp->__value_)) { __next_pointer __np = __p.__node_; @@ -1981,7 +1809,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( __cp->__next_ = __np; __pp->__next_ = static_cast<__next_pointer>(__cp); ++size(); - return iterator(static_cast<__next_pointer>(__cp), this); + return iterator(static_cast<__next_pointer>(__cp)); } return __node_insert_multi(__cp); } @@ -2009,7 +1837,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); __nd = __nd->__next_) { - if (key_eq()(__nd->__upcast()->__value_, __k)) + if ((__nd->__hash() == __hash) && + key_eq()(__nd->__upcast()->__value_, __k)) goto __done; } } @@ -2047,7 +1876,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __inserted = true; } __done: - return pair(iterator(__nd, this), __inserted); + return pair(iterator(__nd), __inserted); } template @@ -2079,16 +1908,13 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( const_iterator __p, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); return __r; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template template _LIBCPP_INLINE_VISIBILITY @@ -2218,7 +2044,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi( __node_insert_multi_perform(__src_ptr, __pn); } } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 template template @@ -2251,7 +2077,6 @@ template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) { - std::__debug_db_invalidate_all(this); __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); @@ -2323,7 +2148,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) - return iterator(__nd, this); + return iterator(__nd); } } } @@ -2350,7 +2175,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) - return const_iterator(__nd, this); + return const_iterator(__nd); } } @@ -2398,12 +2223,9 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) { __next_pointer __np = __p.__node_; - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container erase(iterator) called with an iterator not" - " referring to this container"); - _LIBCPP_ASSERT(__p != end(), - "unordered container erase(iterator) called with a non-dereferenceable iterator"); - iterator __r(__np, this); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(), + "unordered container::erase(iterator) called with a non-dereferenceable iterator"); + iterator __r(__np); ++__r; remove(__p); return __r; @@ -2414,19 +2236,13 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); for (const_iterator __p = __first; __first != __last; __p = __first) { ++__first; erase(__p); } __next_pointer __np = __last.__node_; - return iterator (__np, this); + return iterator (__np); } template @@ -2493,21 +2309,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT __pn->__next_ = __cn->__next_; __cn->__next_ = nullptr; --size(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __dp = __c->end_; __dp != __c->beg_; ) - { - --__dp; - iterator* __i = static_cast((*__dp)->__i_); - if (__i->__node_ == __cn) - { - (*__dp)->__c_ = nullptr; - if (--__c->end_ != __dp) - _VSTD::memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true)); } @@ -2622,10 +2423,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) #endif { - _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value || - this->__node_alloc() == __u.__node_alloc(), - "list::swap: Either propagate_on_container_swap must be true" - " or the allocators must compare equal"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__node_traits::propagate_on_container_swap::value || + this->__node_alloc() == __u.__node_alloc(), + "unordered container::swap: Either propagate_on_container_swap " + "must be true or the allocators must compare equal"); { __node_pointer_pointer __npp = __bucket_list_.release(); __bucket_list_.reset(__u.__bucket_list_.release()); @@ -2644,14 +2445,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) if (__u.size() > 0) __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = __u.__p1_.first().__ptr(); - std::__debug_db_swap(this, std::addressof(__u)); } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()"); __next_pointer __np = __bucket_list_[__n]; size_type __bc = bucket_count(); @@ -2676,38 +2476,6 @@ swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __x.swap(__y); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - -template -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const -{ - return __i->__node_ != nullptr; -} - -template -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const -{ - return false; -} - -template -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -template -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__iterator/access.h b/lib/libcxx/include/__iterator/access.h index 0b8d523017..d7bcb3378d 100644 --- a/lib/libcxx/include/__iterator/access.h +++ b/lib/libcxx/include/__iterator/access.h @@ -69,7 +69,7 @@ end(const _Cp& __c) -> decltype(__c.end()) return __c.end(); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 diff --git a/lib/libcxx/include/__iterator/advance.h b/lib/libcxx/include/__iterator/advance.h index 154c2736f3..04cbe0767a 100644 --- a/lib/libcxx/include/__iterator/advance.h +++ b/lib/libcxx/include/__iterator/advance.h @@ -23,13 +23,15 @@ #include <__utility/declval.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -64,12 +66,12 @@ _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>(_VSTD::__convert_to_integral(__orig_n)); - _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.advance] @@ -101,8 +103,8 @@ public: template _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const { - _LIBCPP_ASSERT(__n >= 0 || bidirectional_iterator<_Ip>, - "If `n < 0`, then `bidirectional_iterator` must be true."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || bidirectional_iterator<_Ip>, + "If `n < 0`, then `bidirectional_iterator` must be true."); // If `I` models `random_access_iterator`, equivalent to `i += n`. if constexpr (random_access_iterator<_Ip>) { @@ -148,8 +150,8 @@ public: template _Sp> _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip& __i, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const { - _LIBCPP_ASSERT((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), - "If `n < 0`, then `bidirectional_iterator && same_as` must be true."); + _LIBCPP_ASSERT_UNCATEGORIZED((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), + "If `n < 0`, then `bidirectional_iterator && same_as` must be true."); // 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)`. @@ -159,9 +161,9 @@ public: __a > 0 ? __a >= __b : __a <= __b; }; - if (const auto __M = __bound_sentinel - __i; __magnitude_geq(__n, __M)) { + if (const auto __m = __bound_sentinel - __i; __magnitude_geq(__n, __m)) { (*this)(__i, __bound_sentinel); - return __n - __M; + return __n - __m; } // Otherwise, equivalent to `ranges::advance(i, n)`. @@ -196,8 +198,10 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ADVANCE_H diff --git a/lib/libcxx/include/__iterator/back_insert_iterator.h b/lib/libcxx/include/__iterator/back_insert_iterator.h index 4c00a7e397..a0083da151 100644 --- a/lib/libcxx/include/__iterator/back_insert_iterator.h +++ b/lib/libcxx/include/__iterator/back_insert_iterator.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -36,7 +39,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -70,4 +73,6 @@ back_inserter(_Container& __x) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/bounded_iter.h b/lib/libcxx/include/__iterator/bounded_iter.h index 2682f2a68a..2a66764887 100644 --- a/lib/libcxx/include/__iterator/bounded_iter.h +++ b/lib/libcxx/include/__iterator/bounded_iter.h @@ -23,6 +23,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Iterator wrapper that carries the valid range it is allowed to access. @@ -35,14 +38,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Arithmetic operations are allowed and the bounds of the resulting iterator // are not checked. Hence, it is possible to create an iterator pointing outside // its range, but it is not possible to dereference it. -template ::value > > +template ::value > > struct __bounded_iter { using value_type = typename iterator_traits<_Iterator>::value_type; using difference_type = typename iterator_traits<_Iterator>::difference_type; using pointer = typename iterator_traits<_Iterator>::pointer; using reference = typename iterator_traits<_Iterator>::reference; using iterator_category = typename iterator_traits<_Iterator>::iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_concept = contiguous_iterator_tag; #endif @@ -78,7 +81,7 @@ private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( _Iterator __current, _Iterator __begin, _Iterator __end) : __current_(__current), __begin_(__begin), __end_(__end) { - _LIBCPP_ASSERT(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); + _LIBCPP_ASSERT_INTERNAL(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); } template @@ -89,19 +92,19 @@ public: // // These operations check that the iterator is dereferenceable, that is within [begin, end). _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); return *__current_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); return std::__to_address(__current_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); return __current_[__n]; } @@ -212,7 +215,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter( #if _LIBCPP_STD_VER <= 17 template -struct __is_cpp17_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {}; +struct __libcpp_is_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {}; #endif template @@ -228,4 +231,6 @@ struct pointer_traits<__bounded_iter<_Iterator> > { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_BOUNDED_ITER_H diff --git a/lib/libcxx/include/__iterator/common_iterator.h b/lib/libcxx/include/__iterator/common_iterator.h index f7883e2c37..95e248d83f 100644 --- a/lib/libcxx/include/__iterator/common_iterator.h +++ b/lib/libcxx/include/__iterator/common_iterator.h @@ -25,6 +25,7 @@ #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> +#include <__memory/addressof.h> #include <__type_traits/is_pointer.h> #include <__utility/declval.h> #include @@ -33,9 +34,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template concept __can_use_postfix_proxy = @@ -46,14 +50,14 @@ template _Sent> requires (!same_as<_Iter, _Sent> && copyable<_Iter>) class common_iterator { struct __proxy { - constexpr const iter_value_t<_Iter>* operator->() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const iter_value_t<_Iter>* operator->() const noexcept { return _VSTD::addressof(__value_); } iter_value_t<_Iter> __value_; }; struct __postfix_proxy { - constexpr const iter_value_t<_Iter>& operator*() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const iter_value_t<_Iter>& operator*() const noexcept { return __value_; } iter_value_t<_Iter> __value_; @@ -62,16 +66,17 @@ class common_iterator { public: variant<_Iter, _Sent> __hold_; - common_iterator() requires default_initializable<_Iter> = default; + _LIBCPP_HIDE_FROM_ABI common_iterator() requires default_initializable<_Iter> = default; - constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} - constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} template requires convertible_to && convertible_to - constexpr common_iterator(const common_iterator<_I2, _S2>& __other) + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(const common_iterator<_I2, _S2>& __other) : __hold_([&]() -> variant<_Iter, _Sent> { - _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to construct from a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__other.__hold_.valueless_by_exception(), + "Attempted to construct from a valueless common_iterator"); if (__other.__hold_.index() == 0) return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)}; return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)}; @@ -80,8 +85,9 @@ public: template requires convertible_to && convertible_to && assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&> - common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { - _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator"); + _LIBCPP_HIDE_FROM_ABI common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { + _LIBCPP_ASSERT_UNCATEGORIZED(!__other.__hold_.valueless_by_exception(), + "Attempted to assign from a valueless common_iterator"); auto __idx = __hold_.index(); auto __other_idx = __other.__hold_.index(); @@ -101,27 +107,30 @@ public: return *this; } - constexpr decltype(auto) operator*() + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } - constexpr decltype(auto) operator*() const + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const requires __dereferenceable { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } template - decltype(auto) operator->() const + _LIBCPP_HIDE_FROM_ABI decltype(auto) operator->() const requires indirectly_readable && (requires(const _I2& __i) { __i.operator->(); } || is_reference_v> || constructible_from, iter_reference_t<_I2>>) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { return _VSTD::__unchecked_get<_Iter>(__hold_); } else if constexpr (is_reference_v>) { @@ -132,13 +141,15 @@ public: } } - common_iterator& operator++() { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_HIDE_FROM_ABI common_iterator& operator++() { + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to increment a non-dereferenceable common_iterator"); ++_VSTD::__unchecked_get<_Iter>(__hold_); return *this; } - decltype(auto) operator++(int) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to increment a non-dereferenceable common_iterator"); if constexpr (forward_iterator<_Iter>) { auto __tmp = *this; ++*this; @@ -157,8 +168,10 @@ public: requires sentinel_for<_Sent, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -176,8 +189,10 @@ public: requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -198,8 +213,10 @@ public: requires sized_sentinel_for<_Sent, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to subtract from a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to subtract a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to subtract from a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to subtract a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -220,7 +237,8 @@ public: noexcept(noexcept(ranges::iter_move(std::declval()))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__i.__hold_), + "Attempted to iter_move a non-dereferenceable common_iterator"); return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); } @@ -228,8 +246,10 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) noexcept(noexcept(ranges::iter_swap(std::declval(), std::declval()))) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); - _LIBCPP_ASSERT(std::holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__x.__hold_), + "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_I2>(__y.__hold_), + "Attempted to iter_swap a non-dereferenceable common_iterator"); return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_)); } }; @@ -274,8 +294,10 @@ struct iterator_traits> { using reference = iter_reference_t<_Iter>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/concepts.h b/lib/libcxx/include/__iterator/concepts.h index d9d40a4249..dd9e8d6ac5 100644 --- a/lib/libcxx/include/__iterator/concepts.h +++ b/lib/libcxx/include/__iterator/concepts.h @@ -46,7 +46,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iterator.concept.readable] template @@ -293,7 +293,7 @@ concept indirectly_copyable_storable = // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle // (both iter_swap and indirectly_swappable require indirectly_readable). -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/counted_iterator.h b/lib/libcxx/include/__iterator/counted_iterator.h index 5fdbff4b48..41b7e57d28 100644 --- a/lib/libcxx/include/__iterator/counted_iterator.h +++ b/lib/libcxx/include/__iterator/counted_iterator.h @@ -34,9 +34,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct __counted_iterator_concept {}; @@ -83,7 +86,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator(_Iter __iter, iter_difference_t<_Iter> __n) : __current_(_VSTD::move(__iter)), __count_(__n) { - _LIBCPP_ASSERT(__n >= 0, "__n must not be negative."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0, "__n must not be negative."); } template @@ -112,7 +115,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator is equal to or past end."); return *__current_; } @@ -120,7 +123,7 @@ public: constexpr decltype(auto) operator*() const requires __dereferenceable { - _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator is equal to or past end."); return *__current_; } @@ -133,7 +136,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator& operator++() { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); ++__current_; --__count_; return *this; @@ -141,21 +144,21 @@ public: _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); --__count_; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { return __current_++; } catch(...) { ++__count_; throw; } #else return __current_++; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator operator++(int) requires forward_iterator<_Iter> { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); counted_iterator __tmp = *this; ++*this; return __tmp; @@ -198,7 +201,7 @@ public: constexpr counted_iterator& operator+=(iter_difference_t<_Iter> __n) requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(__n <= __count_, "Cannot advance iterator past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= __count_, "Cannot advance iterator past end."); __current_ += __n; __count_ -= __n; return *this; @@ -237,9 +240,10 @@ public: constexpr counted_iterator& operator-=(iter_difference_t<_Iter> __n) requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(-__n <= __count_, "Attempt to subtract too large of a size: " - "counted_iterator would be decremented before the " - "first element of its range."); + _LIBCPP_ASSERT_UNCATEGORIZED(-__n <= __count_, + "Attempt to subtract too large of a size: " + "counted_iterator would be decremented before the " + "first element of its range."); __current_ -= __n; __count_ += __n; return *this; @@ -249,7 +253,7 @@ public: constexpr decltype(auto) operator[](iter_difference_t<_Iter> __n) const requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(__n < __count_, "Subscript argument must be less than size."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n < __count_, "Subscript argument must be less than size."); return __current_[__n]; } @@ -280,7 +284,7 @@ public: noexcept(noexcept(ranges::iter_move(__i.__current_))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(__i.__count_ > 0, "Iterator must not be past end of range."); + _LIBCPP_ASSERT_UNCATEGORIZED(__i.__count_ > 0, "Iterator must not be past end of range."); return ranges::iter_move(__i.__current_); } @@ -289,8 +293,8 @@ public: friend constexpr void iter_swap(const counted_iterator& __x, const counted_iterator<_I2>& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) { - _LIBCPP_ASSERT(__x.__count_ > 0 && __y.__count_ > 0, - "Iterators must not be past end of range."); + _LIBCPP_ASSERT_UNCATEGORIZED(__x.__count_ > 0 && __y.__count_ > 0, + "Iterators must not be past end of range."); return ranges::iter_swap(__x.__current_, __y.__current_); } }; @@ -303,8 +307,10 @@ struct iterator_traits> : iterator_traits<_Iter> { add_pointer_t>, void>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_COUNTED_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/cpp17_iterator_concepts.h b/lib/libcxx/include/__iterator/cpp17_iterator_concepts.h new file mode 100644 index 0000000000..c4f49fe742 --- /dev/null +++ b/lib/libcxx/include/__iterator/cpp17_iterator_concepts.h @@ -0,0 +1,185 @@ +//===----------------------------------------------------------------------===// +// +// 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_CPP17_ITERATOR_CONCEPTS_H +#define _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/is_void.h> +#include <__utility/as_const.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 +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +concept __cpp17_move_constructible = is_move_constructible_v<_Tp>; + +template +concept __cpp17_copy_constructible = __cpp17_move_constructible<_Tp> && is_copy_constructible_v<_Tp>; + +template +concept __cpp17_move_assignable = requires(_Tp __lhs, _Tp __rhs) { + { __lhs = std::move(__rhs) } -> same_as<_Tp&>; +}; + +template +concept __cpp17_copy_assignable = __cpp17_move_assignable<_Tp> && requires(_Tp __lhs, _Tp __rhs) { + { __lhs = __rhs } -> same_as<_Tp&>; + { __lhs = std::as_const(__rhs) } -> same_as<_Tp&>; +}; + +template +concept __cpp17_destructible = requires(_Tp __v) { __v.~_Tp(); }; + +template +concept __cpp17_equality_comparable = requires(_Tp __lhs, _Tp __rhs) { + { __lhs == __rhs } -> __boolean_testable; + { std::as_const(__lhs) == __rhs } -> __boolean_testable; + { __lhs == std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) == std::as_const(__rhs) } -> __boolean_testable; +}; + +template +concept __cpp17_default_constructible = is_default_constructible_v<_Tp>; + +template +concept __cpp17_iterator = + __cpp17_copy_constructible<_Iter> && __cpp17_copy_assignable<_Iter> && __cpp17_destructible<_Iter> && + (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>)&&requires(_Iter __iter) { + { *__iter }; + { ++__iter } -> same_as<_Iter&>; + }; + +template +concept __cpp17_input_iterator = + __cpp17_iterator<_Iter> && __cpp17_equality_comparable<_Iter> && requires(_Iter __lhs, _Iter __rhs) { + { __lhs != __rhs } -> __boolean_testable; + { std::as_const(__lhs) != __rhs } -> __boolean_testable; + { __lhs != std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) != std::as_const(__rhs) } -> __boolean_testable; + + { *__lhs } -> same_as<__iter_reference<_Iter>>; + { *std::as_const(__lhs) } -> same_as<__iter_reference<_Iter>>; + + { ++__lhs } -> same_as<_Iter&>; + { (void)__lhs++ }; + { *__lhs++ }; + }; + +template +concept __cpp17_output_iterator = __cpp17_iterator<_Iter> && requires(_Iter __iter, _WriteTo __write) { + { *__iter = std::forward<_WriteTo>(__write) }; + { ++__iter } -> same_as<_Iter&>; + { __iter++ } -> convertible_to; + { *__iter++ = std::forward<_WriteTo>(__write) }; +}; + +template +concept __cpp17_forward_iterator = + __cpp17_input_iterator<_Iter> && __cpp17_default_constructible<_Iter> && requires(_Iter __iter) { + { __iter++ } -> convertible_to; + { *__iter++ } -> same_as<__iter_reference<_Iter>>; + }; + +template +concept __cpp17_bidirectional_iterator = __cpp17_forward_iterator<_Iter> && requires(_Iter __iter) { + { --__iter } -> same_as<_Iter&>; + { __iter-- } -> convertible_to; + { *__iter-- } -> same_as<__iter_reference<_Iter>>; +}; + +template +concept __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Iter> && requires(_Iter __iter, __iter_diff_t<_Iter> __n) { + { __iter += __n } -> same_as<_Iter&>; + + { __iter + __n } -> same_as<_Iter>; + { __n + __iter } -> same_as<_Iter>; + { std::as_const(__iter) + __n } -> same_as<_Iter>; + { __n + std::as_const(__iter) } -> same_as<_Iter>; + + { __iter -= __n } -> same_as<_Iter&>; + { __iter - __n } -> same_as<_Iter>; + { std::as_const(__iter) - __n } -> same_as<_Iter>; + + { __iter - __iter } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - __iter } -> same_as<__iter_diff_t<_Iter>>; + { __iter - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + + { __iter[__n] } -> convertible_to<__iter_reference<_Iter>>; + { std::as_const(__iter)[__n] } -> convertible_to<__iter_reference<_Iter>>; + + { __iter < __iter } -> __boolean_testable; + { std::as_const(__iter) < __iter } -> __boolean_testable; + { __iter < std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) < std::as_const(__iter) } -> __boolean_testable; + + { __iter > __iter } -> __boolean_testable; + { std::as_const(__iter) > __iter } -> __boolean_testable; + { __iter > std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) > std::as_const(__iter) } -> __boolean_testable; + + { __iter >= __iter } -> __boolean_testable; + { std::as_const(__iter) >= __iter } -> __boolean_testable; + { __iter >= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) >= std::as_const(__iter) } -> __boolean_testable; + + { __iter <= __iter } -> __boolean_testable; + { std::as_const(__iter) <= __iter } -> __boolean_testable; + { __iter <= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) <= std::as_const(__iter) } -> __boolean_testable; + }; + +_LIBCPP_END_NAMESPACE_STD + +# ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) static_assert(::std::__cpp17_input_iterator); +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) \ + static_assert(::std::__cpp17_output_iterator); +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) static_assert(::std::__cpp17_forward_iterator); +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_bidirectional_iterator); +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_random_access_iterator); +# else +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) +# endif + +#else // _LIBCPP_STD_VER >= 20 + +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H diff --git a/lib/libcxx/include/__iterator/data.h b/lib/libcxx/include/__iterator/data.h index 88eb752b64..f10680744f 100644 --- a/lib/libcxx/include/__iterator/data.h +++ b/lib/libcxx/include/__iterator/data.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template constexpr _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__iterator/default_sentinel.h b/lib/libcxx/include/__iterator/default_sentinel.h index 669032aa97..d5fb2b699a 100644 --- a/lib/libcxx/include/__iterator/default_sentinel.h +++ b/lib/libcxx/include/__iterator/default_sentinel.h @@ -18,12 +18,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct default_sentinel_t { }; inline constexpr default_sentinel_t default_sentinel{}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/distance.h b/lib/libcxx/include/__iterator/distance.h index 681e20d045..ebe5473371 100644 --- a/lib/libcxx/include/__iterator/distance.h +++ b/lib/libcxx/include/__iterator/distance.h @@ -53,7 +53,7 @@ distance(_InputIter __first, _InputIter __last) return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.distance] @@ -101,7 +101,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/empty.h b/lib/libcxx/include/__iterator/empty.h index 748ca9ecbd..2cd4c7abf4 100644 --- a/lib/libcxx/include/__iterator/empty.h +++ b/lib/libcxx/include/__iterator/empty.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY @@ -37,7 +37,7 @@ template _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/erase_if_container.h b/lib/libcxx/include/__iterator/erase_if_container.h index d7c71a947a..532ec9c1de 100644 --- a/lib/libcxx/include/__iterator/erase_if_container.h +++ b/lib/libcxx/include/__iterator/erase_if_container.h @@ -16,6 +16,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -37,4 +40,6 @@ __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H diff --git a/lib/libcxx/include/__iterator/front_insert_iterator.h b/lib/libcxx/include/__iterator/front_insert_iterator.h index e278359d87..7c77daebb2 100644 --- a/lib/libcxx/include/__iterator/front_insert_iterator.h +++ b/lib/libcxx/include/__iterator/front_insert_iterator.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -36,7 +39,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -68,4 +71,6 @@ front_inserter(_Container& __x) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/incrementable_traits.h b/lib/libcxx/include/__iterator/incrementable_traits.h index 3d06dc0535..604e9580ef 100644 --- a/lib/libcxx/include/__iterator/incrementable_traits.h +++ b/lib/libcxx/include/__iterator/incrementable_traits.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [incrementable.traits] template struct incrementable_traits {}; @@ -71,7 +71,7 @@ using iter_difference_t = typename conditional_t<__is_primary_template >, iterator_traits > >::difference_type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/indirectly_comparable.h b/lib/libcxx/include/__iterator/indirectly_comparable.h index 868190fc48..e60ba25ca7 100644 --- a/lib/libcxx/include/__iterator/indirectly_comparable.h +++ b/lib/libcxx/include/__iterator/indirectly_comparable.h @@ -21,13 +21,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template concept indirectly_comparable = indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/insert_iterator.h b/lib/libcxx/include/__iterator/insert_iterator.h index ecaea61c61..4e833733d2 100644 --- a/lib/libcxx/include/__iterator/insert_iterator.h +++ b/lib/libcxx/include/__iterator/insert_iterator.h @@ -22,9 +22,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template using __insert_iterator_iter_t = ranges::iterator_t<_Container>; #else @@ -46,7 +49,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -78,4 +81,6 @@ inserter(_Container& __x, __insert_iterator_iter_t<_Container> __i) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_INSERT_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/istream_iterator.h b/lib/libcxx/include/__iterator/istream_iterator.h index a056961c10..989902f212 100644 --- a/lib/libcxx/include/__iterator/istream_iterator.h +++ b/lib/libcxx/include/__iterator/istream_iterator.h @@ -47,9 +47,9 @@ private: _Tp __value_; public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr istream_iterator(default_sentinel_t) : istream_iterator() {} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s)) { if (!(*__in_stream_ >> __value_)) @@ -73,11 +73,11 @@ public: operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istream_iterator& __i, default_sentinel_t) { return __i.__in_stream_ == nullptr; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template diff --git a/lib/libcxx/include/__iterator/istreambuf_iterator.h b/lib/libcxx/include/__iterator/istreambuf_iterator.h index bc53a6a1c8..e39fec6d72 100644 --- a/lib/libcxx/include/__iterator/istreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/istreambuf_iterator.h @@ -67,10 +67,10 @@ private: } public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY constexpr istreambuf_iterator(default_sentinel_t) noexcept : istreambuf_iterator() {} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT : __sbuf_(__s.rdbuf()) {} _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT @@ -93,11 +93,11 @@ public: _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const {return __test_for_eof() == __b.__test_for_eof();} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istreambuf_iterator& __i, default_sentinel_t) { return __i.__test_for_eof(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template diff --git a/lib/libcxx/include/__iterator/iter_move.h b/lib/libcxx/include/__iterator/iter_move.h index a7d9413fb8..d9ff90bf65 100644 --- a/lib/libcxx/include/__iterator/iter_move.h +++ b/lib/libcxx/include/__iterator/iter_move.h @@ -23,9 +23,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iterator.cust.move] @@ -97,8 +100,10 @@ template<__dereferenceable _Tp> requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __can_reference; } using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ITER_MOVE_H diff --git a/lib/libcxx/include/__iterator/iter_swap.h b/lib/libcxx/include/__iterator/iter_swap.h index d4c0dca1f6..2fa92f6ef2 100644 --- a/lib/libcxx/include/__iterator/iter_swap.h +++ b/lib/libcxx/include/__iterator/iter_swap.h @@ -26,9 +26,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iter.cust.swap] @@ -106,8 +109,10 @@ concept indirectly_swappable = ranges::iter_swap(__i2, __i1); }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ITER_SWAP_H diff --git a/lib/libcxx/include/__iterator/iterator_traits.h b/lib/libcxx/include/__iterator/iterator_traits.h index c9d8944bfe..248987e9b5 100644 --- a/lib/libcxx/include/__iterator/iterator_traits.h +++ b/lib/libcxx/include/__iterator/iterator_traits.h @@ -43,7 +43,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template using __with_reference = _Tp&; @@ -62,7 +62,7 @@ concept __dereferenceable = requires(_Tp& __t) { template<__dereferenceable _Tp> using iter_reference_t = decltype(*std::declval<_Tp&>()); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template struct _LIBCPP_TEMPLATE_VIS iterator_traits; @@ -72,7 +72,7 @@ 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 {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; #endif @@ -157,7 +157,7 @@ public: static const bool value = decltype(__test<_Tp>(nullptr))::value; }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements // from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to @@ -190,7 +190,7 @@ template concept __cpp17_forward_iterator = __cpp17_input_iterator<_Ip> && constructible_from<_Ip> && - is_lvalue_reference_v> && + is_reference_v> && same_as>, typename indirectly_readable_traits<_Ip>::value_type> && requires(_Ip __i) { @@ -381,7 +381,7 @@ struct iterator_traits : __iterator_traits<_Ip> { using __primary_template = iterator_traits; }; -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template struct __iterator_traits {}; @@ -418,10 +418,10 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits using __primary_template = iterator_traits; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires is_object_v<_Tp> #endif struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> @@ -431,7 +431,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> typedef _Tp* pointer; typedef _Tp& reference; typedef random_access_iterator_tag iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef contiguous_iterator_tag iterator_concept; #endif }; @@ -453,60 +453,60 @@ template struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; template -struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; +using __has_input_iterator_category = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; template -struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {}; +using __has_forward_iterator_category = __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; template -struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {}; +using __has_bidirectional_iterator_category = __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; template -struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; +using __has_random_access_iterator_category = __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; -// __is_cpp17_contiguous_iterator determines if an iterator is known by +// __libcpp_is_contiguous_iterator determines if an iterator is known by // libc++ to be contiguous, either because it advertises itself as such // (in C++20) or because it is a pointer type or a known trivial wrapper // around a (possibly fancy) pointer type, such as __wrap_iter. // Such iterators receive special "contiguous" optimizations in // std::copy and std::sort. // -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template -struct __is_cpp17_contiguous_iterator : _Or< +struct __libcpp_is_contiguous_iterator : _Or< __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>, __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> > {}; #else template -struct __is_cpp17_contiguous_iterator : false_type {}; +struct __libcpp_is_contiguous_iterator : false_type {}; #endif // Any native pointer which is an iterator is also a contiguous iterator. template -struct __is_cpp17_contiguous_iterator<_Up*> : true_type {}; +struct __libcpp_is_contiguous_iterator<_Up*> : true_type {}; template class __wrap_iter; template -struct __is_exactly_cpp17_input_iterator - : public integral_constant::value && - !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value>; template -struct __is_exactly_cpp17_forward_iterator - : public integral_constant::value && - !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value>; template -struct __is_exactly_cpp17_bidirectional_iterator - : public integral_constant::value && - !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value>; template using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; @@ -531,8 +531,23 @@ using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; template using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; -template -using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; +template +using __iter_reference = typename iterator_traits<_Iter>::reference; + +#if _LIBCPP_STD_VER >= 20 + +// [readable.traits] + +// Let `RI` be `remove_cvref_t`. The type `iter_value_t` denotes +// `indirectly_readable_traits::value_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::value_type` otherwise. +// This has to be in this file and not readable_traits.h to break the include cycle between the two. +template +using iter_value_t = typename conditional_t<__is_primary_template > >::value, + indirectly_readable_traits >, + iterator_traits > >::value_type; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/mergeable.h b/lib/libcxx/include/__iterator/mergeable.h index b9f2d081dc..494fda956e 100644 --- a/lib/libcxx/include/__iterator/mergeable.h +++ b/lib/libcxx/include/__iterator/mergeable.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template @@ -34,7 +34,7 @@ concept mergeable = indirectly_copyable<_Input2, _Output> && indirect_strict_weak_order<_Comp, projected<_Input1, _Proj1>, projected<_Input2, _Proj2>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/move_iterator.h b/lib/libcxx/include/__iterator/move_iterator.h index fa806dbaf7..2f79d9a3d2 100644 --- a/lib/libcxx/include/__iterator/move_iterator.h +++ b/lib/libcxx/include/__iterator/move_iterator.h @@ -39,9 +39,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct __move_iter_category_base {}; @@ -59,18 +62,33 @@ template concept __move_iter_comparable = requires { { std::declval() == std::declval<_Sent>() } -> convertible_to; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template class _LIBCPP_TEMPLATE_VIS move_iterator -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 : public __move_iter_category_base<_Iter> #endif { + #if _LIBCPP_STD_VER >= 20 +private: + _LIBCPP_HIDE_FROM_ABI + static constexpr auto __get_iter_concept() { + if constexpr (random_access_iterator<_Iter>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator<_Iter>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator<_Iter>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } +#endif // _LIBCPP_STD_VER >= 20 public: -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_type = _Iter; - using iterator_concept = input_iterator_tag; + using iterator_concept = decltype(__get_iter_concept()); // iterator_category is inherited and not always present using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -79,7 +97,7 @@ public: #else typedef _Iter iterator_type; typedef _If< - __is_cpp17_random_access_iterator<_Iter>::value, + __has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, typename iterator_traits<_Iter>::iterator_category > iterator_category; @@ -93,7 +111,7 @@ public: __libcpp_remove_reference_t<__reference>&&, __reference >::type reference; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} @@ -104,7 +122,7 @@ public: _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const { return __current_; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator() requires is_constructible_v<_Iter> : __current_() {} @@ -171,7 +189,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator--() { --__current_; return *this; } @@ -186,7 +204,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _Sent> friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) @@ -223,7 +241,7 @@ public: { return ranges::iter_swap(__x.__current_, __y.__current_); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 private: template friend class move_iterator; @@ -276,7 +294,7 @@ bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& _ return __x.base() >= __y.base(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _Iter2> inline _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) @@ -284,7 +302,7 @@ auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& { return __x.base() <=> __y.base(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG template @@ -304,7 +322,7 @@ operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) } #endif // !_LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template inline _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iter> operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) @@ -320,7 +338,7 @@ operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterato { return move_iterator<_Iter>(__x.base() + __n); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -332,4 +350,6 @@ make_move_iterator(_Iter __i) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/move_sentinel.h b/lib/libcxx/include/__iterator/move_sentinel.h index 0d7336a1dc..34b3c25417 100644 --- a/lib/libcxx/include/__iterator/move_sentinel.h +++ b/lib/libcxx/include/__iterator/move_sentinel.h @@ -19,9 +19,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template class _LIBCPP_TEMPLATE_VIS move_sentinel @@ -44,7 +47,7 @@ public: move_sentinel& operator=(const move_sentinel<_S2>& __s) { __last_ = __s.base(); return *this; } - constexpr _Sent base() const { return __last_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Sent base() const { return __last_; } private: _Sent __last_ = _Sent(); @@ -52,8 +55,10 @@ private: _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_sentinel); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_MOVE_SENTINEL_H diff --git a/lib/libcxx/include/__iterator/next.h b/lib/libcxx/include/__iterator/next.h index 49970ae248..5aba095dc4 100644 --- a/lib/libcxx/include/__iterator/next.h +++ b/lib/libcxx/include/__iterator/next.h @@ -26,16 +26,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + typename enable_if<__has_input_iterator_category<_InputIter>::value, _InputIter>::type next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { - _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); _VSTD::advance(__x, __n); return __x; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.next] @@ -77,7 +77,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/ostream_iterator.h b/lib/libcxx/include/__iterator/ostream_iterator.h index d16f5a26eb..025712bb1c 100644 --- a/lib/libcxx/include/__iterator/ostream_iterator.h +++ b/lib/libcxx/include/__iterator/ostream_iterator.h @@ -34,7 +34,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/lib/libcxx/include/__iterator/ostreambuf_iterator.h b/lib/libcxx/include/__iterator/ostreambuf_iterator.h index b75f7b6e84..898ef90e7e 100644 --- a/lib/libcxx/include/__iterator/ostreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/ostreambuf_iterator.h @@ -33,7 +33,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/lib/libcxx/include/__iterator/permutable.h b/lib/libcxx/include/__iterator/permutable.h index 28d193eaae..adf88f5065 100644 --- a/lib/libcxx/include/__iterator/permutable.h +++ b/lib/libcxx/include/__iterator/permutable.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template concept permutable = @@ -28,7 +28,7 @@ concept permutable = indirectly_movable_storable<_Iterator, _Iterator> && indirectly_swappable<_Iterator, _Iterator>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/prev.h b/lib/libcxx/include/__iterator/prev.h index af1e1bab11..d31cd8e49b 100644 --- a/lib/libcxx/include/__iterator/prev.h +++ b/lib/libcxx/include/__iterator/prev.h @@ -26,15 +26,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + typename enable_if<__has_input_iterator_category<_InputIter>::value, _InputIter>::type prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { - _LIBCPP_ASSERT(__n <= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); _VSTD::advance(__x, -__n); return __x; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.prev] @@ -70,7 +70,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/projected.h b/lib/libcxx/include/__iterator/projected.h index 19c076b2e5..e74e56d6fb 100644 --- a/lib/libcxx/include/__iterator/projected.h +++ b/lib/libcxx/include/__iterator/projected.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _Proj> struct projected { @@ -34,7 +34,7 @@ struct incrementable_traits> { using difference_type = iter_difference_t<_It>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/ranges_iterator_traits.h b/lib/libcxx/include/__iterator/ranges_iterator_traits.h new file mode 100644 index 0000000000..a30864199d --- /dev/null +++ b/lib/libcxx/include/__iterator/ranges_iterator_traits.h @@ -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___ITERATOR_RANGES_ITERATOR_TRAITS_H +#define _LIBCPP___ITERATOR_RANGES_ITERATOR_TRAITS_H + +#include <__config> +#include <__fwd/pair.h> +#include <__ranges/concepts.h> +#include <__type_traits/add_const.h> +#include <__type_traits/remove_const.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template +using __range_key_type = __remove_const_t::first_type>; + +template +using __range_mapped_type = typename ranges::range_value_t<_Range>::second_type; + +template +using __range_to_alloc_type = + pair::first_type>, + typename ranges::range_value_t<_Range>::second_type>; + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_RANGES_ITERATOR_TRAITS_H diff --git a/lib/libcxx/include/__iterator/readable_traits.h b/lib/libcxx/include/__iterator/readable_traits.h index 8f17757c5a..9e101fc28a 100644 --- a/lib/libcxx/include/__iterator/readable_traits.h +++ b/lib/libcxx/include/__iterator/readable_traits.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [readable.traits] template struct __cond_value_type {}; @@ -74,18 +74,7 @@ template<__has_member_value_type _Tp> struct indirectly_readable_traits<_Tp> : __cond_value_type {}; -template -struct iterator_traits; - -// Let `RI` be `remove_cvref_t`. The type `iter_value_t` denotes -// `indirectly_readable_traits::value_type` if `iterator_traits` names a specialization -// generated from the primary template, and `iterator_traits::value_type` otherwise. -template -using iter_value_t = typename conditional_t<__is_primary_template > >::value, - indirectly_readable_traits >, - iterator_traits > >::value_type; - -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/reverse_access.h b/lib/libcxx/include/__iterator/reverse_access.h index 79b599c47c..b8c5a071cc 100644 --- a/lib/libcxx/include/__iterator/reverse_access.h +++ b/lib/libcxx/include/__iterator/reverse_access.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -93,7 +93,7 @@ auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) return _VSTD::rend(__c); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/reverse_iterator.h b/lib/libcxx/include/__iterator/reverse_iterator.h index f272e03c17..beb10f7f4f 100644 --- a/lib/libcxx/include/__iterator/reverse_iterator.h +++ b/lib/libcxx/include/__iterator/reverse_iterator.h @@ -63,21 +63,21 @@ private: _Iter __t_; // no longer used as of LWG #2360, not removed due to ABI break #endif -#if _LIBCPP_STD_VER > 17 - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>, +#if _LIBCPP_STD_VER >= 20 + static_assert(__has_bidirectional_iterator_category<_Iter>::value || bidirectional_iterator<_Iter>, "reverse_iterator requires It to be a bidirectional iterator."); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 protected: _Iter current; public: using iterator_type = _Iter; - using iterator_category = _If<__is_cpp17_random_access_iterator<_Iter>::value, + using iterator_category = _If<__has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, typename iterator_traits<_Iter>::iterator_category>; using pointer = typename iterator_traits<_Iter>::pointer; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_concept = _If, random_access_iterator_tag, bidirectional_iterator_tag>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -144,7 +144,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator*() const {_Iter __tmp = current; return *--__tmp;} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY constexpr pointer operator->() const requires is_pointer_v<_Iter> || requires(const _Iter __i) { __i.operator->(); } @@ -160,7 +160,7 @@ public: pointer operator->() const { return std::addressof(operator*()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator& operator++() {--current; return *this;} @@ -181,7 +181,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](difference_type __n) const {return *(*this + __n);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const reverse_iterator& __i) noexcept(is_nothrow_copy_constructible_v<_Iter> && @@ -200,18 +200,18 @@ public: auto __ytmp = __y.base(); ranges::iter_swap(--__xtmp, --__ytmp); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() == __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() == __y.base(); } @@ -220,11 +220,11 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() > __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() > __y.base(); } @@ -233,11 +233,11 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() != __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() != __y.base(); } @@ -246,11 +246,11 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() < __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() < __y.base(); } @@ -259,11 +259,11 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() <= __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() <= __y.base(); } @@ -272,16 +272,16 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() >= __y.base() } -> convertible_to; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() >= __y.base(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _Iter2> _LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Iter1, _Iter2> @@ -289,7 +289,7 @@ operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& { return __y.base() <=> __x.base(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG template @@ -318,13 +318,13 @@ operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_i return reverse_iterator<_Iter>(__x.base() - __n); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template requires (!sized_sentinel_for<_Iter1, _Iter2>) inline constexpr bool disable_sized_sentinel_for, reverse_iterator<_Iter2>> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) @@ -365,11 +365,11 @@ class __unconstrained_reverse_iterator { _Iter __iter_; public: - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>); + static_assert(__has_bidirectional_iterator_category<_Iter>::value || bidirectional_iterator<_Iter>); using iterator_type = _Iter; using iterator_category = - _If<__is_cpp17_random_access_iterator<_Iter>::value, random_access_iterator_tag, __iterator_category_type<_Iter>>; + _If<__has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, __iterator_category_type<_Iter>>; using pointer = __iterator_pointer_type<_Iter>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -498,7 +498,7 @@ struct __unwrap_reverse_iter_impl { } }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI constexpr ranges:: subrange>, reverse_iterator>> @@ -512,7 +512,7 @@ template struct __unwrap_iter_impl >, __b> : __unwrap_reverse_iter_impl {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template struct __unwrap_iter_impl>, __b> @@ -526,7 +526,7 @@ template struct __unwrap_iter_impl<__unconstrained_reverse_iterator<__unconstrained_reverse_iterator<_Iter>>, __b> : __unwrap_reverse_iter_impl<__unconstrained_reverse_iterator, __unconstrained_reverse_iterator, _Iter> {}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/size.h b/lib/libcxx/include/__iterator/size.h index 1452bd1d55..625eeb165b 100644 --- a/lib/libcxx/include/__iterator/size.h +++ b/lib/libcxx/include/__iterator/size.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY @@ -34,7 +34,7 @@ template _LIBCPP_INLINE_VISIBILITY constexpr size_t size(const _Tp (&)[_Sz]) noexcept { return _Sz; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_INLINE_VISIBILITY constexpr auto ssize(const _Cont& __c) @@ -52,7 +52,7 @@ constexpr ptrdiff_t ssize(const _Tp (&)[_Sz]) noexcept { return _Sz; } _LIBCPP_DIAGNOSTIC_POP #endif -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/sortable.h b/lib/libcxx/include/__iterator/sortable.h index bcf934f87b..d4d77d6cf3 100644 --- a/lib/libcxx/include/__iterator/sortable.h +++ b/lib/libcxx/include/__iterator/sortable.h @@ -23,14 +23,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template concept sortable = permutable<_Iter> && indirect_strict_weak_order<_Comp, projected<_Iter, _Proj>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/unreachable_sentinel.h b/lib/libcxx/include/__iterator/unreachable_sentinel.h index d77cc99f02..91fd0a57ab 100644 --- a/lib/libcxx/include/__iterator/unreachable_sentinel.h +++ b/lib/libcxx/include/__iterator/unreachable_sentinel.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct unreachable_sentinel_t { template @@ -31,7 +31,7 @@ struct unreachable_sentinel_t { inline constexpr unreachable_sentinel_t unreachable_sentinel{}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__iterator/wrap_iter.h b/lib/libcxx/include/__iterator/wrap_iter.h index 16defc1d8b..774276baa8 100644 --- a/lib/libcxx/include/__iterator/wrap_iter.h +++ b/lib/libcxx/include/__iterator/wrap_iter.h @@ -11,12 +11,12 @@ #define _LIBCPP___ITERATOR_WRAP_ITER_H #include <__config> -#include <__debug> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/pointer_traits.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_convertible.h> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,7 +34,7 @@ public: typedef typename iterator_traits::pointer pointer; typedef typename iterator_traits::reference reference; typedef typename iterator_traits::iterator_category iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef contiguous_iterator_tag iterator_concept; #endif @@ -44,60 +44,23 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter() _NOEXCEPT : __i_() { - _VSTD::__debug_db_insert_i(this); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_Up>& __u, typename enable_if::value>::type* = nullptr) _NOEXCEPT : __i_(__u.base()) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__u)); -#endif } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - __wrap_iter(const __wrap_iter& __x) - : __i_(__x.base()) - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); - } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - __wrap_iter& operator=(const __wrap_iter& __x) - { - if (this != _VSTD::addressof(__x)) - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); - __i_ = __x.__i_; - } - return *this; - } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - ~__wrap_iter() - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__erase_i(this); - } -#endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); return *__i_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); return _VSTD::__to_address(__i_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator++() _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable iterator"); ++__i_; return *this; } @@ -106,8 +69,6 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator--() _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this), - "Attempted to decrement a non-decrementable iterator"); --__i_; return *this; } @@ -117,8 +78,6 @@ public: {__wrap_iter __w(*this); __w += __n; return __w;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator+=(difference_type __n) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__addable(this, __n), - "Attempted to add/subtract an iterator outside its valid range"); __i_ += __n; return *this; } @@ -128,8 +87,6 @@ public: {*this += -__n; return *this;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__subscriptable(this, __n), - "Attempted to subscript an iterator outside its valid range"); return __i_[__n]; } @@ -137,13 +94,8 @@ public: private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - explicit __wrap_iter(const void* __p, iterator_type __x) _NOEXCEPT : __i_(__x) + explicit __wrap_iter(iterator_type __x) _NOEXCEPT : __i_(__x) { - (void)__p; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_ic(this, __p); -#endif } template friend class __wrap_iter; @@ -170,8 +122,6 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)), - "Attempted to compare incomparable iterators"); return __x.base() < __y.base(); } @@ -179,8 +129,6 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), - "Attempted to compare incomparable iterators"); return __x.base() < __y.base(); } @@ -250,8 +198,6 @@ typename __wrap_iter<_Iter1>::difference_type operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT #endif // C++03 { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)), - "Attempted to subtract incompatible iterators"); return __x.base() - __y.base(); } @@ -265,7 +211,7 @@ __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type __n, #if _LIBCPP_STD_VER <= 17 template -struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {}; +struct __libcpp_is_contiguous_iterator<__wrap_iter<_It> > : true_type {}; #endif template diff --git a/lib/libcxx/include/__locale b/lib/libcxx/include/__locale index e0ffa0ca00..5c060ab04c 100644 --- a/lib/libcxx/include/__locale +++ b/lib/libcxx/include/__locale @@ -12,9 +12,12 @@ #include <__availability> #include <__config> +#include <__memory/shared_ptr.h> // __shared_count +#include <__type_traits/make_unsigned.h> #include +#include #include -#include +#include #include #include @@ -22,15 +25,18 @@ #include #include +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include +#else +# include <__std_mbstate_t.h> +#endif + #if defined(_LIBCPP_MSVCRT_LIKE) # include <__support/win32/locale_win32.h> #elif defined(_AIX) || defined(__MVS__) # include <__support/ibm/xlocale.h> #elif defined(__ANDROID__) # include <__support/android/locale_bionic.h> -#elif defined(__sun__) -# include <__support/solaris/xlocale.h> -# include #elif defined(_NEWLIB_VERSION) # include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) @@ -52,64 +58,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) -struct __libcpp_locale_guard { - _LIBCPP_INLINE_VISIBILITY - __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {} - - _LIBCPP_INLINE_VISIBILITY - ~__libcpp_locale_guard() { - if (__old_loc_) - uselocale(__old_loc_); - } - - locale_t __old_loc_; -private: - __libcpp_locale_guard(__libcpp_locale_guard const&); - __libcpp_locale_guard& operator=(__libcpp_locale_guard const&); -}; -#elif defined(_LIBCPP_MSVCRT_LIKE) -struct __libcpp_locale_guard { - __libcpp_locale_guard(locale_t __l) : - __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) { - // Setting the locale can be expensive even when the locale given is - // already the current locale, so do an explicit check to see if the - // current locale is already the one we want. - const char* __lc = __setlocale(nullptr); - // If every category is the same, the locale string will simply be the - // locale name, otherwise it will be a semicolon-separated string listing - // each category. In the second case, we know at least one category won't - // be what we want, so we only have to check the first case. - if (_VSTD::strcmp(__l.__get_locale(), __lc) != 0) { - __locale_all = _strdup(__lc); - if (__locale_all == nullptr) - __throw_bad_alloc(); - __setlocale(__l.__get_locale()); - } - } - ~__libcpp_locale_guard() { - // The CRT documentation doesn't explicitly say, but setlocale() does the - // right thing when given a semicolon-separated list of locale settings - // for the different categories in the same format as returned by - // setlocale(LC_ALL, nullptr). - if (__locale_all != nullptr) { - __setlocale(__locale_all); - free(__locale_all); - } - _configthreadlocale(__status); - } - static const char* __setlocale(const char* __locale) { - const char* __new_locale = setlocale(LC_ALL, __locale); - if (__new_locale == nullptr) - __throw_bad_alloc(); - return __new_locale; - } - int __status; - char* __locale_all = nullptr; -}; -#endif - -class _LIBCPP_TYPE_VIS locale; +class _LIBCPP_EXPORTED_FROM_ABI locale; template _LIBCPP_INLINE_VISIBILITY @@ -121,12 +70,12 @@ _LIBCPP_INLINE_VISIBILITY const _Facet& use_facet(const locale&); -class _LIBCPP_TYPE_VIS locale +class _LIBCPP_EXPORTED_FROM_ABI locale { public: // types: - class _LIBCPP_TYPE_VIS facet; - class _LIBCPP_TYPE_VIS id; + class _LIBCPP_EXPORTED_FROM_ABI facet; + class _LIBCPP_EXPORTED_FROM_ABI id; typedef int category; _LIBCPP_AVAILABILITY_LOCALE_CATEGORY @@ -162,7 +111,9 @@ public: // locale operations: string name() const; bool operator==(const locale&) const; - bool operator!=(const locale& __y) const {return !(*this == __y);} +#if _LIBCPP_STD_VER <= 17 + _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const {return !(*this == __y);} +#endif template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool operator()(const basic_string<_CharT, _Traits, _Allocator>&, @@ -185,7 +136,7 @@ private: template friend const _Facet& use_facet(const locale&); }; -class _LIBCPP_TYPE_VIS locale::facet +class _LIBCPP_EXPORTED_FROM_ABI locale::facet : public __shared_count { protected: @@ -201,7 +152,7 @@ private: void __on_zero_shared() _NOEXCEPT override; }; -class _LIBCPP_TYPE_VIS locale::id +class _LIBCPP_EXPORTED_FROM_ABI locale::id { once_flag __flag_; int32_t __id_; @@ -349,7 +300,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate; template class _LIBCPP_TEMPLATE_VIS collate_byname; template <> -class _LIBCPP_TYPE_VIS collate_byname +class _LIBCPP_EXPORTED_FROM_ABI collate_byname : public collate { locale_t __l_; @@ -369,7 +320,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS collate_byname +class _LIBCPP_EXPORTED_FROM_ABI collate_byname : public collate { locale_t __l_; @@ -401,7 +352,7 @@ locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, // template class ctype -class _LIBCPP_TYPE_VIS ctype_base +class _LIBCPP_EXPORTED_FROM_ABI ctype_base { public: #if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE) @@ -482,7 +433,7 @@ public: static const mask blank = _CTYPE_B; static const mask __regex_word = 0x80; # endif -#elif defined(__sun__) || defined(_AIX) +#elif defined(_AIX) typedef unsigned int mask; static const mask space = _ISSPACE; static const mask print = _ISPRINT; @@ -494,11 +445,7 @@ public: static const mask punct = _ISPUNCT; static const mask xdigit = _ISXDIGIT; static const mask blank = _ISBLANK; -# if defined(_AIX) static const mask __regex_word = 0x8000; -# else - static const mask __regex_word = 0x80; -# endif #elif defined(_NEWLIB_VERSION) // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h. typedef char mask; @@ -561,7 +508,7 @@ template class _LIBCPP_TEMPLATE_VIS ctype; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype +class _LIBCPP_EXPORTED_FROM_ABI ctype : public locale::facet, public ctype_base { @@ -664,7 +611,7 @@ protected: #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype +class _LIBCPP_EXPORTED_FROM_ABI ctype : public locale::facet, public ctype_base { const mask* __tab_; @@ -793,7 +740,7 @@ protected: template class _LIBCPP_TEMPLATE_VIS ctype_byname; template <> -class _LIBCPP_TYPE_VIS ctype_byname +class _LIBCPP_EXPORTED_FROM_ABI ctype_byname : public ctype { locale_t __l_; @@ -812,7 +759,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype_byname +class _LIBCPP_EXPORTED_FROM_ABI ctype_byname : public ctype { locale_t __l_; @@ -926,6 +873,11 @@ isgraph(_CharT __c, const locale& __loc) return std::use_facet >(__loc).is(ctype_base::graph, __c); } +template +_LIBCPP_HIDE_FROM_ABI bool isblank(_CharT __c, const locale& __loc) { + return std::use_facet >(__loc).is(ctype_base::blank, __c); +} + template inline _LIBCPP_INLINE_VISIBILITY _CharT @@ -944,7 +896,7 @@ tolower(_CharT __c, const locale& __loc) // codecvt_base -class _LIBCPP_TYPE_VIS codecvt_base +class _LIBCPP_EXPORTED_FROM_ABI codecvt_base { public: _LIBCPP_INLINE_VISIBILITY codecvt_base() {} @@ -958,7 +910,7 @@ template class _LIBCPP_TEMPLATE_ // template <> class codecvt template <> -class _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1045,7 +997,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1129,7 +1081,7 @@ protected: // template <> class codecvt // deprecated in C++20 template <> -class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1217,7 +1169,7 @@ protected: // template <> class codecvt // C++20 template <> -class _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1305,7 +1257,7 @@ protected: // template <> class codecvt // deprecated in C++20 template <> -class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1393,7 +1345,7 @@ protected: // template <> class codecvt // C++20 template <> -class _LIBCPP_TYPE_VIS codecvt +class _LIBCPP_EXPORTED_FROM_ABI codecvt : public locale::facet, public codecvt_base { @@ -1537,7 +1489,7 @@ struct __narrow_to_utf8<8> _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __narrow_to_utf8<16> +struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<16> : public codecvt { _LIBCPP_INLINE_VISIBILITY @@ -1573,7 +1525,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __narrow_to_utf8<32> +struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<32> : public codecvt { _LIBCPP_INLINE_VISIBILITY @@ -1631,7 +1583,7 @@ struct __widen_from_utf8<8> _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __widen_from_utf8<16> +struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<16> : public codecvt { _LIBCPP_INLINE_VISIBILITY @@ -1667,7 +1619,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __widen_from_utf8<32> +struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<32> : public codecvt { _LIBCPP_INLINE_VISIBILITY @@ -1706,7 +1658,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP template class _LIBCPP_TEMPLATE_VIS numpunct; template <> -class _LIBCPP_TYPE_VIS numpunct +class _LIBCPP_EXPORTED_FROM_ABI numpunct : public locale::facet { public: @@ -1738,7 +1690,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS numpunct +class _LIBCPP_EXPORTED_FROM_ABI numpunct : public locale::facet { public: @@ -1774,7 +1726,7 @@ protected: template class _LIBCPP_TEMPLATE_VIS numpunct_byname; template <> -class _LIBCPP_TYPE_VIS numpunct_byname +class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname : public numpunct { public: @@ -1793,7 +1745,7 @@ private: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS numpunct_byname +class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname : public numpunct { public: diff --git a/lib/libcxx/include/__bsd_locale_defaults.h b/lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h similarity index 91% rename from lib/libcxx/include/__bsd_locale_defaults.h rename to lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h index 4d990482d4..38d36f0aa8 100644 --- a/lib/libcxx/include/__bsd_locale_defaults.h +++ b/lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h @@ -11,8 +11,8 @@ // we will define the mapping from an internal macro to the real BSD symbol. //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___BSD_LOCALE_DEFAULTS_H -#define _LIBCPP___BSD_LOCALE_DEFAULTS_H +#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -33,4 +33,4 @@ #define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__) #define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__) -#endif // _LIBCPP___BSD_LOCALE_DEFAULTS_H +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H diff --git a/lib/libcxx/include/__bsd_locale_fallbacks.h b/lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h similarity index 92% rename from lib/libcxx/include/__bsd_locale_fallbacks.h rename to lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h index 9abd7e7e5f..7776a744d9 100644 --- a/lib/libcxx/include/__bsd_locale_fallbacks.h +++ b/lib/libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h @@ -10,12 +10,18 @@ // of those functions for non-BSD platforms. //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___BSD_LOCALE_FALLBACKS_H -#define _LIBCPP___BSD_LOCALE_FALLBACKS_H +#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H +#include <__locale_dir/locale_base_api/locale_guard.h> +#include #include #include +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -139,4 +145,4 @@ int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___BSD_LOCALE_FALLBACKS_H +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H diff --git a/lib/libcxx/include/__locale_dir/locale_base_api/locale_guard.h b/lib/libcxx/include/__locale_dir/locale_base_api/locale_guard.h new file mode 100644 index 0000000000..0e2e91af7d --- /dev/null +++ b/lib/libcxx/include/__locale_dir/locale_base_api/locale_guard.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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_LOCALE_BASE_API_LOCALE_GUARD_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_LOCALE_GUARD_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) +struct __libcpp_locale_guard { + _LIBCPP_INLINE_VISIBILITY __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {} + + _LIBCPP_INLINE_VISIBILITY ~__libcpp_locale_guard() { + if (__old_loc_) + uselocale(__old_loc_); + } + + locale_t __old_loc_; + +private: + __libcpp_locale_guard(__libcpp_locale_guard const&); + __libcpp_locale_guard& operator=(__libcpp_locale_guard const&); +}; +#elif defined(_LIBCPP_MSVCRT_LIKE) +struct __libcpp_locale_guard { + __libcpp_locale_guard(locale_t __l) : + __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) { + // Setting the locale can be expensive even when the locale given is + // already the current locale, so do an explicit check to see if the + // current locale is already the one we want. + const char* __lc = __setlocale(nullptr); + // If every category is the same, the locale string will simply be the + // locale name, otherwise it will be a semicolon-separated string listing + // each category. In the second case, we know at least one category won't + // be what we want, so we only have to check the first case. + if (_VSTD::strcmp(__l.__get_locale(), __lc) != 0) { + __locale_all = _strdup(__lc); + if (__locale_all == nullptr) + __throw_bad_alloc(); + __setlocale(__l.__get_locale()); + } + } + ~__libcpp_locale_guard() { + // The CRT documentation doesn't explicitly say, but setlocale() does the + // right thing when given a semicolon-separated list of locale settings + // for the different categories in the same format as returned by + // setlocale(LC_ALL, nullptr). + if (__locale_all != nullptr) { + __setlocale(__locale_all); + free(__locale_all); + } + _configthreadlocale(__status); + } + static const char* __setlocale(const char* __locale) { + const char* __new_locale = setlocale(LC_ALL, __locale); + if (__new_locale == nullptr) + __throw_bad_alloc(); + return __new_locale; + } + int __status; + char* __locale_all = nullptr; +}; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_LOCALE_GUARD_H diff --git a/lib/libcxx/include/__mbstate_t.h b/lib/libcxx/include/__mbstate_t.h index 487a6d092c..2b9e719b1f 100644 --- a/lib/libcxx/include/__mbstate_t.h +++ b/lib/libcxx/include/__mbstate_t.h @@ -16,29 +16,39 @@ # pragma GCC system_header #endif -// TODO(ldionne): -// The goal of this header is to provide mbstate_t without having to pull in -// or . This is necessary because we need that type even -// when we don't have (or try to provide) support for wchar_t, because several -// types like std::fpos are defined in terms of mbstate_t. +// The goal of this header is to provide mbstate_t without requiring all of +// or . It's also used by the libc++ versions of +// and to get mbstate_t when the C library doesn't provide +// or , hence the #include_next of those headers instead of #include. +// (e.g. if isn't present in the C library, the libc++ +// will include this header. This header needs to not turn around and cyclically +// include , but fall through to .) // -// This is a gruesome hack, but I don't know how to make it cleaner for -// the time being. +// This does not define std::mbstate_t -- this only brings in the declaration +// in the global namespace. -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -# include // for mbstate_t +// We define this here to support older versions of glibc that do +// not define this for clang. This is also set in libc++'s header, +// and we need to do so here too to avoid a different function signature given +// a different include order. +#ifdef __cplusplus +# define __CORRECT_ISO_CPP_WCHAR_H_PROTO +#endif + +#if defined(_LIBCPP_HAS_MUSL_LIBC) +# define __NEED_mbstate_t +# include +# undef __NEED_mbstate_t #elif __has_include() # include // works on most Unixes #elif __has_include() # include // works on Darwin +#elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) && __has_include_next() +# include_next // fall back to the C standard provider of mbstate_t +#elif __has_include_next() +# include_next // is also required to make mbstate_t visible #else -# error "The library was configured without support for wide-characters, but 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 without on your platform." #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -using ::mbstate_t _LIBCPP_USING_IF_EXISTS; - -_LIBCPP_END_NAMESPACE_STD - #endif // _LIBCPP___MBSTATE_T_H diff --git a/lib/libcxx/include/__mdspan/default_accessor.h b/lib/libcxx/include/__mdspan/default_accessor.h new file mode 100644 index 0000000000..1cc5f15545 --- /dev/null +++ b/lib/libcxx/include/__mdspan/default_accessor.h @@ -0,0 +1,66 @@ +// -*- 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_DEFAULT_ACCESSOR_H +#define _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H + +#include <__config> +#include <__type_traits/is_abstract.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_const.h> +#include +#include + +#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 + +template +struct default_accessor { + static_assert(!is_array_v<_ElementType>, "default_accessor: template argument may not be an array type"); + static_assert(!is_abstract_v<_ElementType>, "default_accessor: template argument may not be an abstract class"); + + using offset_policy = default_accessor; + using element_type = _ElementType; + using reference = _ElementType&; + using data_handle_type = _ElementType*; + + _LIBCPP_HIDE_FROM_ABI constexpr default_accessor() noexcept = default; + template + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>) + _LIBCPP_HIDE_FROM_ABI constexpr default_accessor(default_accessor<_OtherElementType>) noexcept {} + + _LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept { return __p[__i]; } + _LIBCPP_HIDE_FROM_ABI constexpr data_handle_type offset(data_handle_type __p, size_t __i) const noexcept { + return __p + __i; + } +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H diff --git a/lib/libcxx/include/__mdspan/extents.h b/lib/libcxx/include/__mdspan/extents.h new file mode 100644 index 0000000000..a510220d40 --- /dev/null +++ b/lib/libcxx/include/__mdspan/extents.h @@ -0,0 +1,519 @@ +// -*- 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_EXTENTS_H +#define _LIBCPP___MDSPAN_EXTENTS_H + +#include <__assert> +#include <__config> +#include <__type_traits/common_type.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> +#include +#include +#include +#include +#include +#include + +#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 __mdspan_detail { + +// ------------------------------------------------------------------ +// ------------ __static_array -------------------------------------- +// ------------------------------------------------------------------ +// array like class which provides an array of static values with get +template +struct __static_array { + static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...}; + +public: + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); } + _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; } + + template + _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() { + return __get(_Index); + } +}; + +// ------------------------------------------------------------------ +// ------------ __possibly_empty_array ----------------------------- +// ------------------------------------------------------------------ + +// array like class which provides get function and operator [], and +// has a specialization for the size 0 case. +// This is needed to make the __maybe_static_array be truly empty, for +// all static values. + +template +struct __possibly_empty_array { + _Tp __vals_[_Size]; + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t __index) { return __vals_[__index]; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __index) const { return __vals_[__index]; } +}; + +template +struct __possibly_empty_array<_Tp, 0> { + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t) { __libcpp_unreachable(); } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t) const { __libcpp_unreachable(); } +}; + +// ------------------------------------------------------------------ +// ------------ static_partial_sums --------------------------------- +// ------------------------------------------------------------------ + +// Provides a compile time partial sum one can index into + +template +struct __static_partial_sums { + _LIBCPP_HIDE_FROM_ABI static constexpr array __static_partial_sums_impl() { + array __values{_Values...}; + array __partial_sums{{}}; + size_t __running_sum = 0; + for (int __i = 0; __i != sizeof...(_Values); ++__i) { + __partial_sums[__i] = __running_sum; + __running_sum += __values[__i]; + } + return __partial_sums; + } + static constexpr array __result{__static_partial_sums_impl()}; + + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __get(size_t __index) { return __result[__index]; } +}; + +// ------------------------------------------------------------------ +// ------------ __maybe_static_array -------------------------------- +// ------------------------------------------------------------------ + +// array like class which has a mix of static and runtime values but +// only stores the runtime values. +// The type of the static and the runtime values can be different. +// The position of a dynamic value is indicated through a tag value. +template +struct __maybe_static_array { + static_assert(is_convertible<_TStatic, _TDynamic>::value, + "__maybe_static_array: _TStatic must be convertible to _TDynamic"); + static_assert(is_convertible<_TDynamic, _TStatic>::value, + "__maybe_static_array: _TDynamic must be convertible to _TStatic"); + +private: + // Static values member + static constexpr size_t __size_ = sizeof...(_Values); + static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0); + using _StaticValues = __static_array<_TStatic, _Values...>; + using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>; + + // Dynamic values member + _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_; + + // static mapping of indices to the position in the dynamic values array + using _DynamicIdxMap = __static_partial_sums(_Values == _DynTag)...>; + + template + _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence) noexcept { + return _DynamicValues{((void)Indices, 0)...}; + } + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept + : __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {} + + // constructors from dynamic values only -- this covers the case for rank() == 0 + template + requires(sizeof...(_DynVals) == __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) + : __dyn_vals_{static_cast<_TDynamic>(__vals)...} {} + + template + requires(_Size == __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array([[maybe_unused]] const span<_Tp, _Size>& __vals) { + if constexpr (_Size > 0) { + for (size_t __i = 0; __i < _Size; __i++) + __dyn_vals_[__i] = static_cast<_TDynamic>(__vals[__i]); + } + } + + // constructors from all values -- here rank will be greater than 0 + template + requires(sizeof...(_DynVals) != __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) { + static_assert((sizeof...(_DynVals) == __size_), "Invalid number of values."); + _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...}; + for (size_t __i = 0; __i < __size_; __i++) { + _TStatic __static_val = _StaticValues::__get(__i); + if (__static_val == _DynTag) { + __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i]; + } else + // Not catching this could lead to out of bounds errors later + // e.g. using my_mdspan_t = mdspan>; my_mdspan_t = m(new int[5], 5); + // Right-hand-side construction looks ok with allocation and size matching, + // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __values[__i] == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); + } + } + + template + requires(_Size != __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) { + static_assert((_Size == __size_) || (__size_ == dynamic_extent)); + for (size_t __i = 0; __i < __size_; __i++) { + _TStatic __static_val = _StaticValues::__get(__i); + if (__static_val == _DynTag) { + __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]); + } else + // Not catching this could lead to out of bounds errors later + // e.g. using my_mdspan_t = mdspan>; my_mdspan_t = m(new int[N], span(&N)); + // Right-hand-side construction looks ok with allocation and size matching, + // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); + } + } + + // access functions + _LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + return _StaticValues::__get(__i); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + _TStatic __static_val = _StaticValues::__get(__i); + return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val); + } + _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + return __value(__i); + } + + // observers + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return __size_; } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size_dynamic() { return __size_dynamic_; } +}; + +// Function to check whether a value is representable as another type +// value must be a positive integer otherwise returns false +// if _From is not an integral, we just check positivity +template + requires(integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) { + using _To_u = make_unsigned_t<_To>; + using _From_u = make_unsigned_t<_From>; + if constexpr (is_signed_v<_From>) { + if (__value < 0) + return false; + } + if constexpr (static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(numeric_limits<_From>::max())) { + return true; + } else { + return static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(__value); + } +} + +template + requires(!integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) { + if constexpr (is_signed_v<_To>) { + if (static_cast<_To>(__value) < 0) + return false; + } + return true; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(_From... __values) { + return (__mdspan_detail::__is_representable_as<_To>(__values) && ... && true); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(span<_From, _Size> __values) { + for (size_t __i = 0; __i < _Size; __i++) + if (!__mdspan_detail::__is_representable_as<_To>(__values[__i])) + return false; + return true; +} + +} // namespace __mdspan_detail + +// ------------------------------------------------------------------ +// ------------ extents --------------------------------------------- +// ------------------------------------------------------------------ + +// Class to describe the extents of a multi dimensional array. +// Used by mdspan, mdarray and layout mappings. +// See ISO C++ standard [mdspan.extents] + +template +class extents { +public: + // typedefs for integral types used + using index_type = _IndexType; + using size_type = make_unsigned_t; + using rank_type = size_t; + + static_assert(is_integral::value && !is_same::value, + "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"); + +private: + static constexpr rank_type __rank_ = sizeof...(_Extents); + static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0); + + // internal storage type using __maybe_static_array + using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; + [[no_unique_address]] _Values __vals_; + +public: + // [mdspan.extents.obs], observers of multidimensional index space + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; } + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { return __vals_.__value(__r); } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept { + return _Values::__static_value(__r); + } + + // [mdspan.extents.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default; + + // Construction from just dynamic or all values. + // Precondition check is deferred to __maybe_static_array constructor + template + requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) && + (is_nothrow_constructible_v && ...) && + (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_)) + _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept + : __vals_(static_cast(__dynvals)...) { + // Not catching this could lead to out of bounds errors later + // e.g. mdspan m(ptr, dextents(200u)); leads to an extent of -56 on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as(__dynvals...), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + + template + requires(is_convertible_v && + is_nothrow_constructible_v && + (_Size == __rank_ || _Size == __rank_dynamic_)) + explicit(_Size != __rank_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept + : __vals_(span(__exts)) { + // Not catching this could lead to out of bounds errors later + // e.g. mdspan m(ptr, dextents(array(200))); leads to an extent of -56 on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as(span(__exts)), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + + template + requires(is_convertible_v && + is_nothrow_constructible_v && + (_Size == __rank_ || _Size == __rank_dynamic_)) + explicit(_Size != __rank_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept + : __vals_(__exts) { + // Not catching this could lead to out of bounds errors later + // e.g. array a{200u}; mdspan> m(ptr, extents(span(a))); leads to an extent of -56 + // on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as(__exts), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + +private: + // Function to construct extents storage from other extents. + template + requires(_Idx < __rank_) + _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents( + integral_constant, + integral_constant, + const _OtherExtents& __exts, + _DynamicValues... __dynamic_values) noexcept { + if constexpr (static_extent(_Idx) == dynamic_extent) + return __construct_vals_from_extents( + integral_constant(), + integral_constant(), + __exts, + __dynamic_values..., + __exts.extent(_Idx)); + else + return __construct_vals_from_extents( + integral_constant(), integral_constant(), __exts, __dynamic_values...); + } + + template + requires((_Idx == __rank_) && (_DynCount == __rank_dynamic_)) + _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents( + integral_constant, + integral_constant, + const _OtherExtents&, + _DynamicValues... __dynamic_values) noexcept { + return _Values{static_cast(__dynamic_values)...}; + } + +public: + // Converting constructor from other extents specializations + template + requires((sizeof...(_OtherExtents) == sizeof...(_Extents)) && + ((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...)) + explicit((((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...) || + (static_cast>(numeric_limits::max()) < + static_cast>(numeric_limits<_OtherIndexType>::max()))) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept + : __vals_( + __construct_vals_from_extents(integral_constant(), integral_constant(), __other)) { + if constexpr (rank() > 0) { + for (size_t __r = 0; __r < rank(); __r++) { + if constexpr (static_cast>(numeric_limits::max()) < + static_cast>(numeric_limits<_OtherIndexType>::max())) { + // Not catching this could lead to out of bounds errors later + // e.g. dextents> e(dextents(200)) leads to an extent of -56 on e + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as(__other.extent(__r)), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + // Not catching this could lead to out of bounds errors later + // e.g. mdspan> m = mdspan>(new int[5], 5); + // Right-hand-side construction was ok, but m now thinks its range is 10 not 5 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + (_Values::__static_value(__r) == dynamic_extent) || + (static_cast(__other.extent(__r)) == static_cast(_Values::__static_value(__r))), + "extents construction: mismatch of provided arguments with static extents."); + } + } + } + + // Comparison operator + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const extents& __lhs, const extents<_OtherIndexType, _OtherExtents...>& __rhs) noexcept { + if constexpr (rank() != sizeof...(_OtherExtents)) { + return false; + } else { + for (rank_type __r = 0; __r < __rank_; __r++) { + // avoid warning when comparing signed and unsigner integers and pick the wider of two types + using _CommonType = common_type_t; + if (static_cast<_CommonType>(__lhs.extent(__r)) != static_cast<_CommonType>(__rhs.extent(__r))) { + return false; + } + } + } + return true; + } +}; + +// Recursive helper classes to implement dextents alias for extents +namespace __mdspan_detail { + +template > +struct __make_dextents; + +template +struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> { + using type = + 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...>; +}; + +} // end namespace __mdspan_detail + +// [mdspan.extents.dextents], alias template +template +using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type; + +// Deduction guide for extents +template +extents(_IndexTypes...) -> extents; + +namespace __mdspan_detail { + +// Helper type traits for identifying a class as extents. +template +struct __is_extents : false_type {}; + +template +struct __is_extents> : true_type {}; + +template +inline constexpr bool __is_extents_v = __is_extents<_Tp>::value; + +// Function to check whether a set of indices are a multidimensional +// index into extents. This is a word of power in the C++ standard +// requiring that the indices are larger than 0 and smaller than +// the respective extents. + +template + requires(integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) { + if constexpr (is_signed_v<_From>) { + if (__value < 0) + return false; + } + using _Tp = common_type_t<_IndexType, _From>; + return static_cast<_Tp>(__value) < static_cast<_Tp>(__extent); +} + +template + requires(!integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) { + if constexpr (is_signed_v<_IndexType>) { + if (static_cast<_IndexType>(__value) < 0) + return false; + } + return static_cast<_IndexType>(__value) < __extent; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool +__is_multidimensional_index_in_impl(index_sequence<_Idxs...>, const _Extents& __ext, _From... __values) { + return (__mdspan_detail::__is_index_in_extent(__ext.extent(_Idxs), __values) && ...); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_multidimensional_index_in(const _Extents& __ext, _From... __values) { + return __mdspan_detail::__is_multidimensional_index_in_impl( + make_index_sequence<_Extents::rank()>(), __ext, __values...); +} + +} // namespace __mdspan_detail + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_EXTENTS_H diff --git a/lib/libcxx/include/__mdspan/layout_left.h b/lib/libcxx/include/__mdspan/layout_left.h new file mode 100644 index 0000000000..7503dcf77d --- /dev/null +++ b/lib/libcxx/include/__mdspan/layout_left.h @@ -0,0 +1,189 @@ +// -*- 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_LAYOUT_LEFT_H +#define _LIBCPP___MDSPAN_LAYOUT_LEFT_H + +#include <__assert> +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/extents.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/integer_sequence.h> +#include +#include +#include +#include + +#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 + +template +class layout_left::mapping { +public: + static_assert(__mdspan_detail::__is_extents<_Extents>::value, + "layout_left::mapping template argument must be a specialization of extents."); + + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; + +private: + _LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) { + if constexpr (extents_type::rank() == 0) + return true; + + 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); + if (__overflowed) + return false; + } + return true; + } + + static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + "layout_left::mapping product of static extents must be representable as index_type."); + +public: + // [mdspan.layout.left.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // mapping> map(dextents(40,40)); map(10, 3) == -126 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __required_span_size_is_representable(__ext), + "layout_left::mapping extents ctor: product of extents must be representable as index_type."); + } + + template + requires(is_constructible_v) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // mapping> map(mapping>(dextents(40,40))); map(10, 3) == -126 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as(__other.required_span_size()), + "layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + + template + requires(is_constructible_v && _OtherExtents::rank() <= 1) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const layout_right::mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // Note: since this is constraint to rank 1, extents itself would catch the invalid conversion first + // and thus this assertion should never be triggered, but keeping it here for consistency + // layout_left::mapping> map( + // layout_right::mapping>(dextents(200))); map.extents().extent(0) == + // -56 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as(__other.required_span_size()), + "layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + +// FIXME: add when we add other layouts +# if 0 + template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping_&) noexcept; +# endif + + _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.left.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept { + index_type __size = 1; + for (size_t __r = 0; __r < extents_type::rank(); __r++) + __size *= __extents_.extent(__r); + return __size; + } + + template + requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) && + (is_nothrow_constructible_v && ...)) + _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept { + // Mappings are generally meant to be used for accessing allocations and are meant to guarantee to never + // return a value exceeding required_span_size(), which is used to know how large an allocation one needs + // Thus, this is a canonical point in multi-dimensional data structures to make invalid element access checks + // However, mdspan does check this on its own, so for now we avoid double checking in hardened mode + _LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...), + "layout_left::mapping: out of bounds indexing"); + array __idx_a{static_cast(__idx)...}; + return [&](index_sequence<_Pos...>) { + index_type __res = 0; + ((__res = __idx_a[extents_type::rank() - 1 - _Pos] + __extents_.extent(extents_type::rank() - 1 - _Pos) * __res), + ...); + return __res; + }(make_index_sequence()); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept + requires(extents_type::rank() > 0) + { + // While it would be caught by extents itself too, using a too large __r + // is functionally an out of bounds access on the stored information needed to compute strides + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __r < extents_type::rank(), "layout_left::mapping::stride(): invalid rank index"); + index_type __s = 1; + for (rank_type __i = 0; __i < __r; __i++) + __s *= __extents_.extent(__i); + return __s; + } + + template + requires(_OtherExtents::rank() == extents_type::rank()) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept { + return __lhs.extents() == __rhs.extents(); + } + +private: + _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{}; +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUT_LEFT_H diff --git a/lib/libcxx/include/__mdspan/layout_right.h b/lib/libcxx/include/__mdspan/layout_right.h new file mode 100644 index 0000000000..3d814554a1 --- /dev/null +++ b/lib/libcxx/include/__mdspan/layout_right.h @@ -0,0 +1,186 @@ +// -*- 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_LAYOUT_RIGHT_H +#define _LIBCPP___MDSPAN_LAYOUT_RIGHT_H + +#include <__assert> +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/extents.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/integer_sequence.h> +#include +#include +#include + +#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 + +template +class layout_right::mapping { +public: + static_assert(__mdspan_detail::__is_extents<_Extents>::value, + "layout_right::mapping template argument must be a specialization of extents."); + + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; + +private: + _LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) { + if constexpr (extents_type::rank() == 0) + return true; + + 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); + if (__overflowed) + return false; + } + return true; + } + + static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + "layout_right::mapping product of static extents must be representable as index_type."); + +public: + // [mdspan.layout.right.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // mapping> map(dextents(40,40)); map(3, 10) == -126 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __required_span_size_is_representable(__ext), + "layout_right::mapping extents ctor: product of extents must be representable as index_type."); + } + + template + requires(is_constructible_v) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // mapping> map(mapping>(dextents(40,40))); map(3, 10) == -126 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as(__other.required_span_size()), + "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + + template + requires(is_constructible_v && _OtherExtents::rank() <= 1) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const layout_left::mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + // not catching this could lead to out-of-bounds access later when used inside mdspan + // Note: since this is constraint to rank 1, extents itself would catch the invalid conversion first + // and thus this assertion should never be triggered, but keeping it here for consistency + // layout_right::mapping> map( + // layout_left::mapping>(dextents(200))); map.extents().extent(0) == + // -56 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as(__other.required_span_size()), + "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + +// FIXME: add when we add other layouts +# if 0 + template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping_&) noexcept; +# endif + + _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.right.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept { + index_type __size = 1; + for (size_t __r = 0; __r < extents_type::rank(); __r++) + __size *= __extents_.extent(__r); + return __size; + } + + template + requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) && + (is_nothrow_constructible_v && ...)) + _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept { + // Mappings are generally meant to be used for accessing allocations and are meant to guarantee to never + // return a value exceeding required_span_size(), which is used to know how large an allocation one needs + // Thus, this is a canonical point in multi-dimensional data structures to make invalid element access checks + // However, mdspan does check this on its own, so for now we avoid double checking in hardened mode + _LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...), + "layout_right::mapping: out of bounds indexing"); + return [&](index_sequence<_Pos...>) { + index_type __res = 0; + ((__res = static_cast(__idx) + __extents_.extent(_Pos) * __res), ...); + return __res; + }(make_index_sequence()); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept + requires(extents_type::rank() > 0) + { + // While it would be caught by extents itself too, using a too large __r + // is functionally an out of bounds access on the stored information needed to compute strides + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __r < extents_type::rank(), "layout_right::mapping::stride(): invalid rank index"); + index_type __s = 1; + for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--) + __s *= __extents_.extent(__i); + return __s; + } + + template + requires(_OtherExtents::rank() == extents_type::rank()) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept { + return __lhs.extents() == __rhs.extents(); + } + +private: + _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{}; +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUT_RIGHT_H diff --git a/lib/libcxx/include/__mdspan/mdspan.h b/lib/libcxx/include/__mdspan/mdspan.h new file mode 100644 index 0000000000..58f3b9cf1b --- /dev/null +++ b/lib/libcxx/include/__mdspan/mdspan.h @@ -0,0 +1,308 @@ +// -*- 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_MDSPAN_H +#define _LIBCPP___MDSPAN_MDSPAN_H + +#include <__assert> +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/default_accessor.h> +#include <__mdspan/extents.h> +#include <__type_traits/extent.h> +#include <__type_traits/is_abstract.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__type_traits/rank.h> +#include <__type_traits/remove_all_extents.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_pointer.h> +#include <__type_traits/remove_reference.h> +#include <__utility/integer_sequence.h> +#include +#include +#include +#include +#include + +#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 + +// Helper for lightweight test checking that one did pass a layout policy as LayoutPolicy template argument +namespace __mdspan_detail { +template +concept __has_invalid_mapping = !requires { typename _Layout::template mapping<_Extents>; }; +} // namespace __mdspan_detail + +template > +class mdspan { +private: + static_assert(__mdspan_detail::__is_extents_v<_Extents>, + "mdspan: Extents template parameter must be a specialization of extents."); + static_assert(!is_array_v<_ElementType>, "mdspan: ElementType template parameter may not be an array type"); + static_assert(!is_abstract_v<_ElementType>, "mdspan: ElementType template parameter may not be an abstract class"); + static_assert(is_same_v<_ElementType, typename _AccessorPolicy::element_type>, + "mdspan: ElementType template parameter must match AccessorPolicy::element_type"); + static_assert(!__mdspan_detail::__has_invalid_mapping<_LayoutPolicy, _Extents>, + "mdspan: LayoutPolicy template parameter is invalid. A common mistake is to pass a layout mapping " + "instead of a layout policy"); + +public: + using extents_type = _Extents; + using layout_type = _LayoutPolicy; + using accessor_type = _AccessorPolicy; + using mapping_type = typename layout_type::template mapping; + using element_type = _ElementType; + using value_type = remove_cv_t; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using data_handle_type = typename accessor_type::data_handle_type; + using reference = typename accessor_type::reference; + + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return extents_type::rank(); } + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept { + return extents_type::static_extent(__r); + } + _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { + return __map_.extents().extent(__r); + }; + +public: + //-------------------------------------------------------------------------------- + // [mdspan.mdspan.cons], mdspan constructors, assignment, and destructor + + _LIBCPP_HIDE_FROM_ABI constexpr mdspan() + requires((extents_type::rank_dynamic() > 0) && is_default_constructible_v && + is_default_constructible_v && is_default_constructible_v) + = default; + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(const mdspan&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(mdspan&&) = default; + + template + requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) && + (is_nothrow_constructible_v && ...) && + ((sizeof...(_OtherIndexTypes) == rank()) || (sizeof...(_OtherIndexTypes) == rank_dynamic())) && + is_constructible_v && is_default_constructible_v) + _LIBCPP_HIDE_FROM_ABI explicit constexpr mdspan(data_handle_type __p, _OtherIndexTypes... __exts) + : __ptr_(std::move(__p)), __map_(extents_type(static_cast(std::move(__exts))...)), __acc_{} {} + + template + requires(is_convertible_v && + is_nothrow_constructible_v && + ((_Size == rank()) || (_Size == rank_dynamic())) && is_constructible_v && + is_default_constructible_v) + explicit(_Size != rank_dynamic()) + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(data_handle_type __p, const array<_OtherIndexType, _Size>& __exts) + : __ptr_(std::move(__p)), __map_(extents_type(__exts)), __acc_{} {} + + template + requires(is_convertible_v && + is_nothrow_constructible_v && + ((_Size == rank()) || (_Size == rank_dynamic())) && is_constructible_v && + is_default_constructible_v) + explicit(_Size != rank_dynamic()) + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(data_handle_type __p, span<_OtherIndexType, _Size> __exts) + : __ptr_(std::move(__p)), __map_(extents_type(__exts)), __acc_{} {} + + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(data_handle_type __p, const extents_type& __exts) + requires(is_default_constructible_v && is_constructible_v) + : __ptr_(std::move(__p)), __map_(__exts), __acc_{} {} + + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(data_handle_type __p, const mapping_type& __m) + requires(is_default_constructible_v) + : __ptr_(std::move(__p)), __map_(__m), __acc_{} {} + + _LIBCPP_HIDE_FROM_ABI constexpr mdspan(data_handle_type __p, const mapping_type& __m, const accessor_type& __a) + : __ptr_(std::move(__p)), __map_(__m), __acc_(__a) {} + + template + requires(is_constructible_v&> && + is_constructible_v) + explicit(!is_convertible_v&, mapping_type> || + !is_convertible_v) + _LIBCPP_HIDE_FROM_ABI constexpr mdspan( + const mdspan<_OtherElementType, _OtherExtents, _OtherLayoutPolicy, _OtherAccessor>& __other) + : __ptr_(__other.__ptr_), __map_(__other.__map_), __acc_(__other.__acc_) { + static_assert(is_constructible_v, + "mdspan: incompatible data_handle_type for mdspan construction"); + static_assert( + is_constructible_v, "mdspan: incompatible extents for mdspan construction"); + + // The following precondition is part of the standard, but is unlikely to be triggered. + // The extents constructor checks this and the mapping must be storing the extents, since + // its extents() function returns a const reference to extents_type. + // The only way this can be triggered is if the mapping conversion constructor would for example + // always construct its extents() only from the dynamic extents, instead of from the other extents. + if constexpr (rank() > 0) { + for (size_t __r = 0; __r < rank(); __r++) { + // Not catching this could lead to out of bounds errors later + // e.g. mdspan, non_checking_layout> m = + // mdspan, non_checking_layout>(ptr, 200); leads to an extent of -56 on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + (static_extent(__r) == dynamic_extent) || + (static_cast(__other.extent(__r)) == static_cast(static_extent(__r))), + "mdspan: conversion mismatch of source dynamic extents with static extents"); + } + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr mdspan& operator=(const mdspan&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr mdspan& operator=(mdspan&&) = default; + + //-------------------------------------------------------------------------------- + // [mdspan.mdspan.members], members + + template + requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) && + (is_nothrow_constructible_v && ...) && + (sizeof...(_OtherIndexTypes) == rank())) + _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](_OtherIndexTypes... __indices) const { + // Note the standard layouts would also check this, but user provided ones may not, so we + // check the precondition here + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__is_multidimensional_index_in(extents(), __indices...), + "mdspan: operator[] out of bounds access"); + return __acc_.access(__ptr_, __map_(static_cast(std::move(__indices))...)); + } + + template + requires(is_convertible_v && + is_nothrow_constructible_v) + _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](const array< _OtherIndexType, rank()>& __indices) const { + return __acc_.access(__ptr_, [&](index_sequence<_Idxs...>) { + return __map_(__indices[_Idxs]...); + }(make_index_sequence())); + } + + template + requires(is_convertible_v && + is_nothrow_constructible_v) + _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](span<_OtherIndexType, rank()> __indices) const { + return __acc_.access(__ptr_, [&](index_sequence<_Idxs...>) { + return __map_(__indices[_Idxs]...); + }(make_index_sequence())); + } + + _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { + // Could leave this as only checked in debug mode: semantically size() is never + // guaranteed to be related to any accessible range + _LIBCPP_ASSERT_UNCATEGORIZED( + false == ([&](index_sequence<_Idxs...>) { + size_type __prod = 1; + return (__builtin_mul_overflow(__prod, extent(_Idxs), &__prod) || ... || false); + }(make_index_sequence())), + "mdspan: size() is not representable as size_type"); + return [&](index_sequence<_Idxs...>) { + return ((static_cast(__map_.extents().extent(_Idxs))) * ... * size_type(1)); + }(make_index_sequence()); + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { + return [&](index_sequence<_Idxs...>) { + return (rank() > 0) && ((__map_.extents().extent(_Idxs) == index_type(0)) || ... || false); + }(make_index_sequence()); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(mdspan& __x, mdspan& __y) noexcept { + swap(__x.__ptr_, __y.__ptr_); + swap(__x.__map_, __y.__map_); + swap(__x.__acc_, __y.__acc_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __map_.extents(); }; + _LIBCPP_HIDE_FROM_ABI constexpr const data_handle_type& data_handle() const noexcept { return __ptr_; }; + _LIBCPP_HIDE_FROM_ABI constexpr const mapping_type& mapping() const noexcept { return __map_; }; + _LIBCPP_HIDE_FROM_ABI constexpr const accessor_type& accessor() const noexcept { return __acc_; }; + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); }; + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); }; + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); }; + + _LIBCPP_HIDE_FROM_ABI constexpr bool is_unique() const { return __map_.is_unique(); }; + _LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const { return __map_.is_exhaustive(); }; + _LIBCPP_HIDE_FROM_ABI constexpr bool is_strided() const { return __map_.is_strided(); }; + _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const { return __map_.stride(__r); }; + +private: + _LIBCPP_NO_UNIQUE_ADDRESS data_handle_type __ptr_{}; + _LIBCPP_NO_UNIQUE_ADDRESS mapping_type __map_{}; + _LIBCPP_NO_UNIQUE_ADDRESS accessor_type __acc_{}; + + template + friend class mdspan; +}; + +template + requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) +explicit mdspan(_ElementType*, _OtherIndexTypes...) + -> mdspan<_ElementType, dextents>; + +template + requires(is_pointer_v>) +mdspan(_Pointer&&) -> mdspan>, extents>; + +template + requires(is_array_v<_CArray> && (rank_v<_CArray> == 1)) +mdspan(_CArray&) -> mdspan, extents>>; + +template +mdspan(_ElementType*, const array<_OtherIndexType, _Size>&) -> mdspan<_ElementType, dextents>; + +template +mdspan(_ElementType*, span<_OtherIndexType, _Size>) -> mdspan<_ElementType, dextents>; + +// This one is necessary because all the constructors take `data_handle_type`s, not +// `_ElementType*`s, and `data_handle_type` is taken from `accessor_type::data_handle_type`, which +// seems to throw off automatic deduction guides. +template +mdspan(_ElementType*, const extents<_OtherIndexType, _ExtentsPack...>&) + -> mdspan<_ElementType, extents<_OtherIndexType, _ExtentsPack...>>; + +template +mdspan(_ElementType*, const _MappingType&) + -> mdspan<_ElementType, typename _MappingType::extents_type, typename _MappingType::layout_type>; + +template +mdspan(const typename _AccessorType::data_handle_type, const _MappingType&, const _AccessorType&) + -> mdspan; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_MDSPAN_H diff --git a/lib/libcxx/include/__memory/align.h b/lib/libcxx/include/__memory/align.h index c6792206b0..bbb995f4a8 100644 --- a/lib/libcxx/include/__memory/align.h +++ b/lib/libcxx/include/__memory/align.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); +_LIBCPP_EXPORTED_FROM_ABI void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/aligned_alloc.h b/lib/libcxx/include/__memory/aligned_alloc.h new file mode 100644 index 0000000000..786963c72d --- /dev/null +++ b/lib/libcxx/include/__memory/aligned_alloc.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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___MEMORY_ALIGNED_ALLOC_H +#define _LIBCPP___MEMORY_ALIGNED_ALLOC_H + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION + +// Low-level helpers to call the aligned allocation and deallocation functions +// on the target platform. This is used to implement libc++'s own memory +// allocation routines -- if you need to allocate memory inside the library, +// chances are that you want to use `__libcpp_allocate` instead. +// +// Returns the allocated memory, or `nullptr` on failure. +inline _LIBCPP_HIDE_FROM_ABI +void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { +# if defined(_LIBCPP_MSVCRT_LIKE) + return ::_aligned_malloc(__size, __alignment); +# elif _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_C11_ALIGNED_ALLOC) + // aligned_alloc() requires that __size is a multiple of __alignment, + // but for C++ [new.delete.general], only states "if the value of an + // alignment argument passed to any of these functions is not a valid + // alignment value, the behavior is undefined". + // To handle calls such as ::operator new(1, std::align_val_t(128)), we + // round __size up to the next multiple of __alignment. + size_t __rounded_size = (__size + __alignment - 1) & ~(__alignment - 1); + // Rounding up could have wrapped around to zero, so we have to add another + // max() ternary to the actual call site to avoid succeeded in that case. + return ::aligned_alloc(__alignment, __size > __rounded_size ? __size : __rounded_size); +# else + void* __result = nullptr; + (void)::posix_memalign(&__result, __alignment, __size); + // If posix_memalign fails, __result is unmodified so we still return `nullptr`. + return __result; +# endif +} + +inline _LIBCPP_HIDE_FROM_ABI +void __libcpp_aligned_free(void* __ptr) { +#if defined(_LIBCPP_MSVCRT_LIKE) + ::_aligned_free(__ptr); +#else + ::free(__ptr); +#endif +} + +#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_ALIGNED_ALLOC_H diff --git a/lib/libcxx/include/__memory/allocate_at_least.h b/lib/libcxx/include/__memory/allocate_at_least.h index ef205f855c..8d8ad071e2 100644 --- a/lib/libcxx/include/__memory/allocate_at_least.h +++ b/lib/libcxx/include/__memory/allocate_at_least.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template struct allocation_result { _Pointer ptr; @@ -55,7 +55,7 @@ __allocation_result::pointer> __allocate_at_le return {__alloc.allocate(__n), __n}; } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/allocation_guard.h b/lib/libcxx/include/__memory/allocation_guard.h index 424598cc81..f63b17430e 100644 --- a/lib/libcxx/include/__memory/allocation_guard.h +++ b/lib/libcxx/include/__memory/allocation_guard.h @@ -11,6 +11,7 @@ #define _LIBCPP___MEMORY_ALLOCATION_GUARD_H #include <__config> +#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__utility/move.h> #include @@ -19,6 +20,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Helper class to allocate memory using an Allocator in an exception safe @@ -55,9 +59,29 @@ struct __allocation_guard { _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { - if (__ptr_ != nullptr) { - allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + __destroy(); + } + + _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete; + _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 { + if (std::addressof(__other) != this) { + __destroy(); + + __alloc_ = std::move(__other.__alloc_); + __n_ = __other.__n_; + __ptr_ = __other.__ptr_; + __other.__ptr_ = nullptr; } + + return *this; } _LIBCPP_HIDE_FROM_ABI @@ -73,6 +97,13 @@ struct __allocation_guard { } private: + _LIBCPP_HIDE_FROM_ABI + void __destroy() _NOEXCEPT { + if (__ptr_ != nullptr) { + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + } + } + _Alloc __alloc_; _Size __n_; _Pointer __ptr_; @@ -80,4 +111,6 @@ private: _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_ALLOCATION_GUARD_H diff --git a/lib/libcxx/include/__memory/allocator.h b/lib/libcxx/include/__memory/allocator.h index 54c9b78d52..47e1ef926a 100644 --- a/lib/libcxx/include/__memory/allocator.h +++ b/lib/libcxx/include/__memory/allocator.h @@ -11,6 +11,7 @@ #define _LIBCPP___MEMORY_ALLOCATOR_H #include <__config> +#include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator_traits.h> #include <__type_traits/is_constant_evaluated.h> @@ -20,7 +21,6 @@ #include <__utility/forward.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -98,8 +98,7 @@ public: typedef true_type propagate_on_container_move_assignment; typedef true_type is_always_equal; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - allocator() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -116,7 +115,7 @@ public: } } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<_Tp*> allocate_at_least(size_t __n) { return {allocate(__n), __n}; @@ -187,8 +186,7 @@ public: typedef true_type propagate_on_container_move_assignment; typedef true_type is_always_equal; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - allocator() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -205,7 +203,7 @@ public: } } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result allocate_at_least(size_t __n) { return {allocate(__n), __n}; @@ -264,10 +262,14 @@ template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} +#if _LIBCPP_STD_VER <= 17 + template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MEMORY_ALLOCATOR_H diff --git a/lib/libcxx/include/__memory/allocator_arg_t.h b/lib/libcxx/include/__memory/allocator_arg_t.h index 15f8c98c4c..4d9c115f72 100644 --- a/lib/libcxx/include/__memory/allocator_arg_t.h +++ b/lib/libcxx/include/__memory/allocator_arg_t.h @@ -25,10 +25,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; }; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; -#else -/* inline */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +#if _LIBCPP_STD_VER >= 17 +inline constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +#elif !defined(_LIBCPP_CXX03_LANG) +constexpr allocator_arg_t allocator_arg = allocator_arg_t(); #endif #ifndef _LIBCPP_CXX03_LANG diff --git a/lib/libcxx/include/__memory/allocator_traits.h b/lib/libcxx/include/__memory/allocator_traits.h index 3a23b47c74..4658098d64 100644 --- a/lib/libcxx/include/__memory/allocator_traits.h +++ b/lib/libcxx/include/__memory/allocator_traits.h @@ -300,7 +300,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits __enable_if_t::value> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static void construct(allocator_type&, _Tp* __p, _Args&&... __args) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _VSTD::construct_at(__p, _VSTD::forward<_Args>(__args)...); #else ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); @@ -319,7 +319,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits __enable_if_t::value> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type&, _Tp* __p) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _VSTD::destroy_at(__p); #else __p->~_Tp(); @@ -401,6 +401,25 @@ struct __is_cpp17_copy_insertable<_Alloc, __enable_if_t< : __is_cpp17_move_insertable<_Alloc> { }; +// ASan choices +#ifndef _LIBCPP_HAS_NO_ASAN +# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 +#endif + +#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS +template +struct __asan_annotate_container_with_allocator +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1600 + : true_type {}; +# else + // TODO(LLVM-18): Remove the special-casing + : false_type {}; +# endif + +template +struct __asan_annotate_container_with_allocator > : true_type {}; +#endif + #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/assume_aligned.h b/lib/libcxx/include/__memory/assume_aligned.h index a1fd2441f9..00c2928dcc 100644 --- a/lib/libcxx/include/__memory/assume_aligned.h +++ b/lib/libcxx/include/__memory/assume_aligned.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template [[nodiscard]] @@ -34,12 +34,12 @@ constexpr _Tp* assume_aligned(_Tp* __ptr) { if (is_constant_evaluated()) { return __ptr; } else { - _LIBCPP_ASSERT(reinterpret_cast(__ptr) % _Np == 0, "Alignment assumption is violated"); + _LIBCPP_ASSERT_UNCATEGORIZED(reinterpret_cast(__ptr) % _Np == 0, "Alignment assumption is violated"); return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Np)); } } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/builtin_new_allocator.h b/lib/libcxx/include/__memory/builtin_new_allocator.h index cd1a866ca6..ab449ad299 100644 --- a/lib/libcxx/include/__memory/builtin_new_allocator.h +++ b/lib/libcxx/include/__memory/builtin_new_allocator.h @@ -28,10 +28,10 @@ struct __builtin_new_allocator { struct __builtin_new_deleter { typedef void* pointer_type; - _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) : __size_(__size), __align_(__align) {} - void operator()(void* __p) const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const _NOEXCEPT { _VSTD::__libcpp_deallocate(__p, __size_, __align_); } @@ -42,25 +42,25 @@ struct __builtin_new_allocator { typedef unique_ptr __holder_t; - static __holder_t __allocate_bytes(size_t __s, size_t __align) { + _LIBCPP_HIDE_FROM_ABI static __holder_t __allocate_bytes(size_t __s, size_t __align) { return __holder_t(_VSTD::__libcpp_allocate(__s, __align), __builtin_new_deleter(__s, __align)); } - static void __deallocate_bytes(void* __p, size_t __s, + _LIBCPP_HIDE_FROM_ABI static void __deallocate_bytes(void* __p, size_t __s, size_t __align) _NOEXCEPT { _VSTD::__libcpp_deallocate(__p, __s, __align); } template _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static __holder_t __allocate_type(size_t __n) { + _LIBCPP_HIDE_FROM_ABI static __holder_t __allocate_type(size_t __n) { return __allocate_bytes(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); } template _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { __deallocate_bytes(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); } }; diff --git a/lib/libcxx/include/__memory/compressed_pair.h b/lib/libcxx/include/__memory/compressed_pair.h index 8093d7c931..f24b2bac56 100644 --- a/lib/libcxx/include/__memory/compressed_pair.h +++ b/lib/libcxx/include/__memory/compressed_pair.h @@ -13,7 +13,7 @@ #include <__config> #include <__fwd/get.h> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_indices.h> +#include <__tuple/tuple_indices.h> #include <__type_traits/decay.h> #include <__type_traits/dependent_type.h> #include <__type_traits/enable_if.h> @@ -31,6 +31,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Tag used to default initialize one or both of the pair's elements. @@ -46,7 +49,7 @@ struct __compressed_pair_elem { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_() {} - template ::type>::value> > + template >::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u) : __value_(std::forward<_Up>(__u)) {} @@ -75,7 +78,7 @@ struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_type() {} - template ::type>::value> > + template >::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u) : __value_type(std::forward<_Up>(__u)) {} @@ -174,4 +177,6 @@ void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H diff --git a/lib/libcxx/include/__memory/concepts.h b/lib/libcxx/include/__memory/concepts.h index 12d7bf85ed..97cc3583ec 100644 --- a/lib/libcxx/include/__memory/concepts.h +++ b/lib/libcxx/include/__memory/concepts.h @@ -19,6 +19,7 @@ #include <__ranges/concepts.h> #include <__type_traits/is_reference.h> #include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> // TODO(modules): This should not be required #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -62,7 +63,7 @@ concept __nothrow_forward_range = } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/construct_at.h b/lib/libcxx/include/__memory/construct_at.h index 14484dd6aa..a032c33b47 100644 --- a/lib/libcxx/include/__memory/construct_at.h +++ b/lib/libcxx/include/__memory/construct_at.h @@ -26,26 +26,29 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // construct_at -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template ()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) { - _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"); - return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...); + _LIBCPP_ASSERT_UNCATEGORIZED(__location != nullptr, "null pointer given to construct_at"); + return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); } #endif template ()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 return std::construct_at(__location, std::forward<_Args>(__args)...); #else - return _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"), + return _LIBCPP_ASSERT_UNCATEGORIZED(__location != nullptr, "null pointer given to construct_at"), ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); #endif } @@ -62,16 +65,16 @@ _ForwardIterator __destroy(_ForwardIterator, _ForwardIterator); template ::value, int>::type = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at"); + _LIBCPP_ASSERT_UNCATEGORIZED(__loc != nullptr, "null pointer given to destroy_at"); __loc->~_Tp(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template ::value, int>::type = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at"); - _VSTD::__destroy(_VSTD::begin(*__loc), _VSTD::end(*__loc)); + _LIBCPP_ASSERT_UNCATEGORIZED(__loc != nullptr, "null pointer given to destroy_at"); + std::__destroy(std::begin(*__loc), std::end(*__loc)); } #endif @@ -79,7 +82,7 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) { for (; __first != __last; ++__first) - _VSTD::__destroy_at(_VSTD::addressof(*__first)); + std::__destroy_at(std::addressof(*__first)); return __first; } @@ -93,38 +96,40 @@ _BidirectionalIterator __reverse_destroy(_BidirectionalIterator __first, _Bidire return __last; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { - _VSTD::__destroy_at(__loc); + std::__destroy_at(__loc); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template , int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { - _VSTD::__destroy_at(__loc); + std::__destroy_at(__loc); } #endif template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy(_ForwardIterator __first, _ForwardIterator __last) { - (void)_VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last)); + (void)std::__destroy(std::move(__first), std::move(__last)); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { for (; __n > 0; (void)++__first, --__n) - _VSTD::__destroy_at(_VSTD::addressof(*__first)); + std::__destroy_at(std::addressof(*__first)); return __first; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H diff --git a/lib/libcxx/include/__memory/pointer_traits.h b/lib/libcxx/include/__memory/pointer_traits.h index c4f20def45..c33e7bd43f 100644 --- a/lib/libcxx/include/__memory/pointer_traits.h +++ b/lib/libcxx/include/__memory/pointer_traits.h @@ -200,7 +200,7 @@ template , _IsFancyPointer<_Pointer> >::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename decay::__call(std::declval()))>::type +__decay_t::__call(std::declval()))> __to_address(const _Pointer& __p) _NOEXCEPT { return __to_address_helper<_Pointer>::__call(__p); } @@ -223,7 +223,7 @@ struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to } }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template inline _LIBCPP_INLINE_VISIBILITY constexpr auto to_address(_Tp *__p) noexcept { diff --git a/lib/libcxx/include/__memory/ranges_construct_at.h b/lib/libcxx/include/__memory/ranges_construct_at.h index e63585d1ab..ed800f4a75 100644 --- a/lib/libcxx/include/__memory/ranges_construct_at.h +++ b/lib/libcxx/include/__memory/ranges_construct_at.h @@ -13,7 +13,7 @@ #include <__concepts/destructible.h> #include <__config> #include <__iterator/incrementable_traits.h> -#include <__iterator/readable_traits.h> +#include <__iterator/iterator_traits.h> #include <__memory/concepts.h> #include <__memory/construct_at.h> #include <__ranges/access.h> @@ -28,9 +28,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { // construct_at @@ -118,8 +121,10 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_RANGES_CONSTRUCT_AT_H diff --git a/lib/libcxx/include/__memory/ranges_uninitialized_algorithms.h b/lib/libcxx/include/__memory/ranges_uninitialized_algorithms.h index 15c78e20ba..01c3e01003 100644 --- a/lib/libcxx/include/__memory/ranges_uninitialized_algorithms.h +++ b/lib/libcxx/include/__memory/ranges_uninitialized_algorithms.h @@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -45,7 +45,7 @@ struct __fn { template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel> requires default_initializable> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { using _ValueType = remove_reference_t>; return _VSTD::__uninitialized_default_construct<_ValueType>( _VSTD::move(__first), _VSTD::move(__last)); @@ -53,7 +53,7 @@ struct __fn { template <__nothrow_forward_range _ForwardRange> requires default_initializable> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } }; @@ -71,7 +71,7 @@ namespace __uninitialized_default_construct_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator> requires default_initializable> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const { using _ValueType = remove_reference_t>; return _VSTD::__uninitialized_default_construct_n<_ValueType>(_VSTD::move(__first), __n); @@ -92,7 +92,7 @@ struct __fn { template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel> requires default_initializable> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { using _ValueType = remove_reference_t>; return _VSTD::__uninitialized_value_construct<_ValueType>( _VSTD::move(__first), _VSTD::move(__last)); @@ -100,7 +100,7 @@ struct __fn { template <__nothrow_forward_range _ForwardRange> requires default_initializable> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } }; @@ -118,7 +118,7 @@ namespace __uninitialized_value_construct_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator> requires default_initializable> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const { using _ValueType = remove_reference_t>; return _VSTD::__uninitialized_value_construct_n<_ValueType>(_VSTD::move(__first), __n); @@ -140,14 +140,14 @@ struct __fn { __nothrow_sentinel_for<_ForwardIterator> _Sentinel, class _Tp> requires constructible_from, const _Tp&> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const { using _ValueType = remove_reference_t>; return _VSTD::__uninitialized_fill<_ValueType>(_VSTD::move(__first), _VSTD::move(__last), __x); } template <__nothrow_forward_range _ForwardRange, class _Tp> requires constructible_from, const _Tp&> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range, const _Tp& __x) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range, const _Tp& __x) const { return (*this)(ranges::begin(__range), ranges::end(__range), __x); } }; @@ -165,7 +165,7 @@ namespace __uninitialized_fill_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator, class _Tp> requires constructible_from, const _Tp&> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n, const _Tp& __x) const { using _ValueType = remove_reference_t>; @@ -192,7 +192,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel2> requires constructible_from, iter_reference_t<_InputIterator>> - uninitialized_copy_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const { using _ValueType = remove_reference_t>; @@ -203,7 +203,7 @@ struct __fn { template requires constructible_from, range_reference_t<_InputRange>> - uninitialized_copy_result, borrowed_iterator_t<_OutputRange>> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result, borrowed_iterator_t<_OutputRange>> operator()( _InputRange&& __in_range, _OutputRange&& __out_range) const { return (*this)(ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range)); @@ -228,7 +228,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel> requires constructible_from, iter_reference_t<_InputIterator>> - uninitialized_copy_n_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_n_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, iter_difference_t<_InputIterator> __n, _OutputIterator __ofirst, _Sentinel __olast) const { using _ValueType = remove_reference_t>; @@ -257,7 +257,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel2> requires constructible_from, iter_rvalue_reference_t<_InputIterator>> - uninitialized_move_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const { using _ValueType = remove_reference_t>; auto __iter_move = [](auto&& __iter) -> decltype(auto) { return ranges::iter_move(__iter); }; @@ -268,7 +268,7 @@ struct __fn { template requires constructible_from, range_rvalue_reference_t<_InputRange>> - uninitialized_move_result, borrowed_iterator_t<_OutputRange>> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_result, borrowed_iterator_t<_OutputRange>> operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const { return (*this)(ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range)); @@ -293,7 +293,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel> requires constructible_from, iter_rvalue_reference_t<_InputIterator>> - uninitialized_move_n_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_n_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, iter_difference_t<_InputIterator> __n, _OutputIterator __ofirst, _Sentinel __olast) const { using _ValueType = remove_reference_t>; @@ -312,7 +312,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/raw_storage_iterator.h b/lib/libcxx/include/__memory/raw_storage_iterator.h index 11971de0fa..df7ef5afe7 100644 --- a/lib/libcxx/include/__memory/raw_storage_iterator.h +++ b/lib/libcxx/include/__memory/raw_storage_iterator.h @@ -39,7 +39,7 @@ private: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/lib/libcxx/include/__memory/shared_ptr.h b/lib/libcxx/include/__memory/shared_ptr.h index f0ffa26abf..dce44a7b37 100644 --- a/lib/libcxx/include/__memory/shared_ptr.h +++ b/lib/libcxx/include/__memory/shared_ptr.h @@ -29,17 +29,32 @@ #include <__memory/pointer_traits.h> #include <__memory/uninitialized_algorithms.h> #include <__memory/unique_ptr.h> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_bounded_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_unbounded_array.h> +#include <__type_traits/nat.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_extent.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <__verbose_abort> #include -#include // abort #include #include #include #include #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) -# include +# include <__atomic/memory_order.h> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -105,12 +120,12 @@ __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT #endif } -class _LIBCPP_EXCEPTION_ABI bad_weak_ptr +class _LIBCPP_EXPORTED_FROM_ABI bad_weak_ptr : public std::exception { public: - bad_weak_ptr() _NOEXCEPT = default; - bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI bad_weak_ptr() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; ~bad_weak_ptr() _NOEXCEPT override; const char* what() const _NOEXCEPT override; }; @@ -118,16 +133,16 @@ public: _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_weak_ptr() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_weak_ptr(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_weak_ptr was thrown in -fno-exceptions mode"); #endif } template class _LIBCPP_TEMPLATE_VIS weak_ptr; -class _LIBCPP_TYPE_VIS __shared_count +class _LIBCPP_EXPORTED_FROM_ABI __shared_count { __shared_count(const __shared_count&); __shared_count& operator=(const __shared_count&); @@ -166,7 +181,7 @@ public: } }; -class _LIBCPP_TYPE_VIS __shared_weak_count +class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count { long __shared_weak_owners_; @@ -220,12 +235,12 @@ public: : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} #ifndef _LIBCPP_HAS_NO_RTTI - const void* __get_deleter(const type_info&) const _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* __get_deleter(const type_info&) const _NOEXCEPT override; #endif private: - void __on_zero_shared() _NOEXCEPT override; - void __on_zero_shared_weak() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override; }; #ifndef _LIBCPP_HAS_NO_RTTI @@ -295,8 +310,8 @@ struct __shared_ptr_emplace _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); } private: - void __on_zero_shared() _NOEXCEPT override { -#if _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 if constexpr (is_same_v) { __get_elem()->~_Tp(); } else { @@ -309,7 +324,7 @@ private: #endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type; using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer; _ControlBlockAlloc __tmp(*__get_alloc()); @@ -336,13 +351,13 @@ private: _LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); } - _Alloc* __get_alloc() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair); _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); return __alloc; } - _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); _Tp *__elem = reinterpret_cast<_Tp*>(__second); @@ -433,10 +448,10 @@ struct __is_array_deletable<_Ptr, decltype(delete[] std::declval<_Ptr>())> : tru template ()(std::declval<_Pt>()))> -static true_type __well_formed_deleter_test(int); +true_type __well_formed_deleter_test(int); template -static false_type __well_formed_deleter_test(...); +false_type __well_formed_deleter_test(...); template struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; @@ -450,7 +465,7 @@ struct __shared_ptr_deleter_ctor_reqs }; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) -# define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) +# define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI #endif @@ -459,7 +474,7 @@ template class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { public: -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef weak_ptr<_Tp> weak_type; typedef remove_extent_t<_Tp> element_type; #else @@ -494,7 +509,7 @@ public: #endif >::value > > - explicit shared_ptr(_Yp* __p) : __ptr_(__p) { + _LIBCPP_HIDE_FROM_ABI explicit shared_ptr(_Yp* __p) : __ptr_(__p) { unique_ptr<_Yp> __hold(__p); typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT> _CntrlBlk; @@ -508,10 +523,10 @@ public: shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT> _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG @@ -520,14 +535,14 @@ public: __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); #endif // not _LIBCPP_CXX03_LANG __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template::value> > @@ -535,10 +550,10 @@ public: shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk; typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; typedef __allocator_destructor<_A2> _D2; @@ -552,14 +567,14 @@ public: #endif // not _LIBCPP_CXX03_LANG __cntrl_ = _VSTD::addressof(*__hold2.release()); __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template @@ -567,10 +582,10 @@ public: shared_ptr(nullptr_t __p, _Dp __d) : __ptr_(nullptr) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; typedef __shared_ptr_pointer _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG @@ -578,14 +593,14 @@ public: #else __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); #endif // not _LIBCPP_CXX03_LANG -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template @@ -593,10 +608,10 @@ public: shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) : __ptr_(nullptr) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef __shared_ptr_pointer _CntrlBlk; typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; typedef __allocator_destructor<_A2> _D2; @@ -609,14 +624,14 @@ public: _CntrlBlk(__p, __d, __a); #endif // not _LIBCPP_CXX03_LANG __cntrl_ = _VSTD::addressof(*__hold2.release()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template @@ -629,6 +644,18 @@ public: __cntrl_->__add_shared(); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 + template + _LIBCPP_HIDE_FROM_ABI shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept + : __ptr_(__p), + __cntrl_(__r.__cntrl_) { + __r.__ptr_ = nullptr; + __r.__cntrl_ = nullptr; + } +#endif + _LIBCPP_HIDE_FROM_ABI shared_ptr(const shared_ptr& __r) _NOEXCEPT : __ptr_(__r.__ptr_), @@ -699,7 +726,7 @@ public: shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 if (__ptr_ == nullptr) __cntrl_ = nullptr; else @@ -722,7 +749,7 @@ public: shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 if (__ptr_ == nullptr) __cntrl_ = nullptr; else @@ -895,7 +922,7 @@ public: return __cntrl_ == __p.__cntrl_; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t operator[](ptrdiff_t __i) const { @@ -975,7 +1002,7 @@ private: template friend class _LIBCPP_TEMPLATE_VIS weak_ptr; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; template @@ -1024,7 +1051,7 @@ shared_ptr<_Tp> make_shared_for_overwrite() #endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template struct __sp_aligned_storage { @@ -1084,7 +1111,7 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count ~__unbounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: - void __on_zero_shared() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { #if _LIBCPP_STD_VER >= 20 if constexpr (is_same_v) { std::__reverse_destroy(__data_, __data_ + __count_); @@ -1098,7 +1125,7 @@ private: #endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _AlignedStorage = __sp_aligned_storage; using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>; using _PointerTraits = pointer_traits::pointer>; @@ -1170,7 +1197,7 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> ~__bounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: - void __on_zero_shared() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { #if _LIBCPP_STD_VER >= 20 if constexpr (is_same_v) { std::__reverse_destroy(__data_, __data_ + _Count); @@ -1184,7 +1211,7 @@ private: #endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, __bounded_array_control_block>; using _PointerTraits = pointer_traits::pointer>; @@ -1214,9 +1241,9 @@ shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&& ... return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // bounded array variants template::value>> @@ -1308,7 +1335,7 @@ shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template inline _LIBCPP_INLINE_VISIBILITY @@ -1368,7 +1395,7 @@ operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT #endif // _LIBCPP_STD_VER <= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) noexcept @@ -1477,7 +1504,7 @@ operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT #endif // _LIBCPP_STD_VER <= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, nullptr_t) noexcept @@ -1504,6 +1531,15 @@ static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), static_cast::element_type*>(__r.get())); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY shared_ptr<_Tp> @@ -1514,6 +1550,16 @@ dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + auto* __p = dynamic_cast::element_type*>(__r.get()); + return __p ? shared_ptr<_Tp>(std::move(__r), __p) : shared_ptr<_Tp>(); +} +#endif + template _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT @@ -1522,6 +1568,15 @@ const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), const_cast::element_type*>(__r.get())); +} +#endif + template _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT @@ -1531,6 +1586,15 @@ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), reinterpret_cast::element_type*>(__r.get())); +} +#endif + #ifndef _LIBCPP_HAS_NO_RTTI template @@ -1547,7 +1611,7 @@ template class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { public: -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef remove_extent_t<_Tp> element_type; #else typedef _Tp element_type; @@ -1574,7 +1638,7 @@ public: template _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r, typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type = 0) _NOEXCEPT; - ~weak_ptr(); + _LIBCPP_HIDE_FROM_ABI ~weak_ptr(); _LIBCPP_INLINE_VISIBILITY weak_ptr& operator=(weak_ptr const& __r) _NOEXCEPT; @@ -1618,7 +1682,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool expired() const _NOEXCEPT {return __cntrl_ == nullptr || __cntrl_->use_count() == 0;} - shared_ptr<_Tp> lock() const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> lock() const _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT @@ -1632,7 +1696,7 @@ public: template friend class _LIBCPP_TEMPLATE_VIS shared_ptr; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; #endif @@ -1808,7 +1872,7 @@ weak_ptr<_Tp>::lock() const _NOEXCEPT return __r; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template struct owner_less; #else template struct owner_less; @@ -1845,7 +1909,7 @@ struct _LIBCPP_TEMPLATE_VIS owner_less > {return __x.owner_before(__y);} }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <> struct _LIBCPP_TEMPLATE_VIS owner_less { @@ -1891,7 +1955,7 @@ public: shared_ptr<_Tp const> shared_from_this() const {return shared_ptr(__weak_this_);} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY weak_ptr<_Tp> weak_from_this() _NOEXCEPT { return __weak_this_; } @@ -1899,7 +1963,7 @@ public: _LIBCPP_INLINE_VISIBILITY weak_ptr weak_from_this() const _NOEXCEPT { return __weak_this_; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 template friend class shared_ptr; }; @@ -1929,7 +1993,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p); #if !defined(_LIBCPP_HAS_NO_THREADS) -class _LIBCPP_TYPE_VIS __sp_mut +class _LIBCPP_EXPORTED_FROM_ABI __sp_mut { void* __lx_; public: @@ -1941,10 +2005,10 @@ private: __sp_mut(const __sp_mut&); __sp_mut& operator=(const __sp_mut&); - friend _LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*); + friend _LIBCPP_EXPORTED_FROM_ABI __sp_mut& __get_sp_mut(const void*); }; -_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR +_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR __sp_mut& __get_sp_mut(const void*); template diff --git a/lib/libcxx/include/__memory/swap_allocator.h b/lib/libcxx/include/__memory/swap_allocator.h index c6e1751f4d..90851cb79c 100644 --- a/lib/libcxx/include/__memory/swap_allocator.h +++ b/lib/libcxx/include/__memory/swap_allocator.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc& __a1, _Alloc& __a2, true_type) -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) @@ -39,7 +39,7 @@ __swap_allocator(_Alloc&, _Alloc&, false_type) _NOEXCEPT {} template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc& __a1, _Alloc& __a2) -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) diff --git a/lib/libcxx/include/__memory/temp_value.h b/lib/libcxx/include/__memory/temp_value.h index 164688b15f..3ce8b4bcbb 100644 --- a/lib/libcxx/include/__memory/temp_value.h +++ b/lib/libcxx/include/__memory/temp_value.h @@ -32,7 +32,7 @@ struct __temp_value { #endif _Alloc &__a; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp *__addr() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp *__addr() { #ifdef _LIBCPP_CXX03_LANG return reinterpret_cast<_Tp*>(std::addressof(__v)); #else @@ -40,15 +40,15 @@ struct __temp_value { #endif } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & get() { return *__addr(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & get() { return *__addr(); } template - _LIBCPP_NO_CFI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_CONSTEXPR_SINCE_CXX20 __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { _Traits::construct(__a, __addr(), std::forward<_Args>(__args)...); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__temp_value() { _Traits::destroy(__a, __addr()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__temp_value() { _Traits::destroy(__a, __addr()); } }; _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/uninitialized_algorithms.h b/lib/libcxx/include/__memory/uninitialized_algorithms.h index 90aecb7d6a..2b68df8e6d 100644 --- a/lib/libcxx/include/__memory/uninitialized_algorithms.h +++ b/lib/libcxx/include/__memory/uninitialized_algorithms.h @@ -12,6 +12,8 @@ #include <__algorithm/copy.h> #include <__algorithm/move.h> +#include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> @@ -58,12 +60,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast) { _ForwardIterator __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __ifirst != __ilast && __idx != __olast; ++__ifirst, (void)++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -90,12 +92,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _Sentinel __olast) { _ForwardIterator __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0 && __idx != __olast; ++__ifirst, (void)++__idx, (void)--__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -121,13 +123,13 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) { _ForwardIterator __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(__x); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -154,13 +156,13 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { _ForwardIterator __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(__x); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -180,7 +182,7 @@ _ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const return _VSTD::__uninitialized_fill_n<_ValueType>(__first, __n, __x); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // uninitialized_default_construct @@ -188,12 +190,12 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -217,12 +219,12 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -245,12 +247,12 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -274,12 +276,12 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -304,13 +306,13 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast, _IterMove __iter_move) { auto __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __ifirst != __ilast && __idx != __olast; ++__idx, (void)++__ifirst) { ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -338,12 +340,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _Sentinel __olast, _IterMove __iter_move) { auto __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0 && __idx != __olast; ++__idx, (void)++__ifirst, --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -371,7 +373,7 @@ uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir // This function assumes that destructors do not throw, and that the allocator is bound to // the correct type. template::value + __has_bidirectional_iterator_category<_BidirIter>::value >> _LIBCPP_HIDE_FROM_ABI constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept { @@ -512,7 +514,7 @@ __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _B __guard.__complete(); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 // Destroy all elements in [__first, __last) from left to right using allocator destruction. template @@ -545,7 +547,7 @@ private: // already copied elements are destroyed in reverse order of their construction. template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 -__uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { +__uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { auto __destruct_first = __first2; auto __guard = std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); @@ -565,14 +567,16 @@ template struct __allocator_has_trivial_copy_construct, _Type> : true_type {}; template , + class _In, + class _RawTypeIn = __remove_const_t<_In>, + class _Out, __enable_if_t< - // using _RawType because of the allocator extension - is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value && - __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type* -__uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __last1, _Type* __first2) { + // using _RawTypeIn because of the allocator extension + is_trivially_copy_constructible<_RawTypeIn>::value && is_trivially_copy_assignable<_RawTypeIn>::value && + is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value && + __allocator_has_trivial_copy_construct<_Alloc, _RawTypeIn>::value>* = nullptr> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out* +__uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) { // TODO: Remove the const_cast once we drop support for std::allocator if (__libcpp_is_constant_evaluated()) { while (__first1 != __last1) { @@ -582,10 +586,17 @@ __uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __la } return __first2; } else { - return std::copy(__first1, __last1, const_cast<_RawType*>(__first2)); + return std::copy(__first1, __last1, const_cast<_RawTypeIn*>(__first2)); } } +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { + auto __unwrapped_range = std::__unwrap_range(__first1, __last1); + auto __result = std::__uninitialized_allocator_copy_impl(__alloc, __unwrapped_range.first, __unwrapped_range.second, std::__unwrap_iter(__first2)); + return std::__rewrap_iter(__first2, __result); +} + // Move-construct the elements [__first1, __last1) into [__first2, __first2 + N) // if the move constructor is noexcept, where N is distance(__first1, __last1). // @@ -600,7 +611,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_alloc auto __guard = std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); #else allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1)); diff --git a/lib/libcxx/include/__memory/unique_ptr.h b/lib/libcxx/include/__memory/unique_ptr.h index 9cdbda8eba..5a96878971 100644 --- a/lib/libcxx/include/__memory/unique_ptr.h +++ b/lib/libcxx/include/__memory/unique_ptr.h @@ -44,6 +44,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -115,7 +118,7 @@ struct __unique_ptr_deleter_sfinae<_Deleter&> { }; #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) -# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) +# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI #endif @@ -556,7 +559,7 @@ bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template requires three_way_comparable_with::pointer, typename unique_ptr<_T2, _D2>::pointer> @@ -650,7 +653,7 @@ operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return !(nullptr < __x); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template requires three_way_comparable< typename unique_ptr<_T1, _D1>::pointer> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 @@ -660,7 +663,7 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) { } #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template struct __unique_if @@ -697,7 +700,7 @@ template typename __unique_if<_Tp>::__unique_array_known_bound make_unique(_Args&&...) = delete; -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 20 @@ -743,4 +746,6 @@ struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H diff --git a/lib/libcxx/include/__memory/uses_allocator.h b/lib/libcxx/include/__memory/uses_allocator.h index fe89704027..f82ac17963 100644 --- a/lib/libcxx/include/__memory/uses_allocator.h +++ b/lib/libcxx/include/__memory/uses_allocator.h @@ -49,9 +49,9 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator { }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template -inline constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; +inline constexpr bool uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__memory/uses_allocator_construction.h b/lib/libcxx/include/__memory/uses_allocator_construction.h index 0f63b080da..a2e4f6e26f 100644 --- a/lib/libcxx/include/__memory/uses_allocator_construction.h +++ b/lib/libcxx/include/__memory/uses_allocator_construction.h @@ -23,6 +23,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 @@ -83,7 +86,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) std::forward_as_tuple(std::forward<_Vp>(__v))); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template , int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept { @@ -109,7 +112,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>&& __pai std::forward_as_tuple(std::get<1>(std::move(__pair)))); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template , int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept { @@ -218,4 +221,6 @@ uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Ar _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H diff --git a/lib/libcxx/include/__memory_resource/memory_resource.h b/lib/libcxx/include/__memory_resource/memory_resource.h index 02fdd081cc..418f36dc9b 100644 --- a/lib/libcxx/include/__memory_resource/memory_resource.h +++ b/lib/libcxx/include/__memory_resource/memory_resource.h @@ -9,14 +9,16 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H +#include <__availability> #include <__config> +#include <__fwd/memory_resource.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -24,7 +26,7 @@ namespace pmr { // [mem.res.class] -class _LIBCPP_TYPE_VIS memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource { static const size_t __max_align = alignof(max_align_t); public: @@ -51,25 +53,38 @@ private: // [mem.res.eq] -inline _LIBCPP_HIDE_FROM_ABI bool operator==(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { +inline _LIBCPP_AVAILABILITY_PMR _LIBCPP_HIDE_FROM_ABI bool +operator==(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { return &__lhs == &__rhs || __lhs.is_equal(__rhs); } -inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { +# if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_AVAILABILITY_PMR _LIBCPP_HIDE_FROM_ABI bool +operator!=(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { return !(__lhs == __rhs); } +# endif + // [mem.res.global] -[[__gnu__::__returns_nonnull__]] _LIBCPP_FUNC_VIS memory_resource* get_default_resource() noexcept; -[[__gnu__::__returns_nonnull__]] _LIBCPP_FUNC_VIS memory_resource* set_default_resource(memory_resource*) noexcept; -[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_FUNC_VIS memory_resource* new_delete_resource() noexcept; -[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_FUNC_VIS memory_resource* null_memory_resource() noexcept; +[[__gnu__::__returns_nonnull__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +get_default_resource() noexcept; + +[[__gnu__::__returns_nonnull__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +set_default_resource(memory_resource*) noexcept; + +[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +new_delete_resource() noexcept; + +[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +null_memory_resource() noexcept; } // namespace pmr _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H diff --git a/lib/libcxx/include/__memory_resource/monotonic_buffer_resource.h b/lib/libcxx/include/__memory_resource/monotonic_buffer_resource.h index 5b0d246258..0c83f1ebc8 100644 --- a/lib/libcxx/include/__memory_resource/monotonic_buffer_resource.h +++ b/lib/libcxx/include/__memory_resource/monotonic_buffer_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H +#include <__availability> #include <__config> #include <__memory/addressof.h> #include <__memory_resource/memory_resource.h> @@ -18,7 +19,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -26,7 +27,7 @@ namespace pmr { // [mem.res.monotonic.buffer] -class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI monotonic_buffer_resource : public memory_resource { static const size_t __default_buffer_capacity = 1024; static const size_t __default_buffer_alignment = 16; @@ -35,7 +36,9 @@ class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource { char* __start_; char* __cur_; size_t __align_; - size_t __allocation_size() { return (reinterpret_cast(this) - __start_) + sizeof(*this); } + _LIBCPP_HIDE_FROM_ABI size_t __allocation_size() { + return (reinterpret_cast(this) - __start_) + sizeof(*this); + } void* __try_allocate_from_chunk(size_t, size_t); }; @@ -115,6 +118,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H diff --git a/lib/libcxx/include/__memory_resource/polymorphic_allocator.h b/lib/libcxx/include/__memory_resource/polymorphic_allocator.h index f7b9a0b408..8fcce65ad2 100644 --- a/lib/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/lib/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -10,6 +10,7 @@ #define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H #include <__assert> +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__utility/exception_guard.h> @@ -26,7 +27,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,7 +40,7 @@ template -class _LIBCPP_TEMPLATE_VIS polymorphic_allocator { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator { public: using value_type = _ValueType; @@ -50,7 +51,7 @@ public: _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {} - polymorphic_allocator(const polymorphic_allocator&) = default; + _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default; template _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept @@ -68,35 +69,35 @@ public: } _LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) { - _LIBCPP_ASSERT(__n <= __max_size(), "deallocate called for size which exceeds max_size()"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= __max_size(), "deallocate called for size which exceeds max_size()"); __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType)); } # if _LIBCPP_STD_VER >= 20 - [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] void* + [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) { return __res_->allocate(__nbytes, __alignment); } - void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + _LIBCPP_HIDE_FROM_ABI void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { __res_->deallocate(__ptr, __nbytes, __alignment); } template - [[nodiscard]] _Type* allocate_object(size_t __n = 1) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* allocate_object(size_t __n = 1) { if (numeric_limits::max() / sizeof(_Type) < __n) std::__throw_bad_array_new_length(); return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type))); } template - void deallocate_object(_Type* __ptr, size_t __n = 1) { + _LIBCPP_HIDE_FROM_ABI void deallocate_object(_Type* __ptr, size_t __n = 1) { deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type)); } template - [[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* new_object(_CtorArgs&&... __ctor_args) { _Type* __ptr = allocate_object<_Type>(); auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); }); construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...); @@ -105,7 +106,7 @@ public: } template - void delete_object(_Type* __ptr) { + _LIBCPP_HIDE_FROM_ABI void delete_object(_Type* __ptr) { destroy(__ptr); deallocate_object(__ptr); } @@ -207,17 +208,21 @@ operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator< return *__lhs.resource() == *__rhs.resource(); } +# if _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept { return !(__lhs == __rhs); } +# endif + } // namespace pmr _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__memory_resource/pool_options.h b/lib/libcxx/include/__memory_resource/pool_options.h index 11585a0e3b..442959836c 100644 --- a/lib/libcxx/include/__memory_resource/pool_options.h +++ b/lib/libcxx/include/__memory_resource/pool_options.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -24,7 +24,7 @@ namespace pmr { // [mem.res.pool.options] -struct _LIBCPP_TYPE_VIS pool_options { +struct _LIBCPP_EXPORTED_FROM_ABI pool_options { size_t max_blocks_per_chunk = 0; size_t largest_required_pool_block = 0; }; @@ -33,6 +33,6 @@ struct _LIBCPP_TYPE_VIS pool_options { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_POOL_OPTIONS_H diff --git a/lib/libcxx/include/__memory_resource/synchronized_pool_resource.h b/lib/libcxx/include/__memory_resource/synchronized_pool_resource.h index 1877147ca1..b261fb0b19 100644 --- a/lib/libcxx/include/__memory_resource/synchronized_pool_resource.h +++ b/lib/libcxx/include/__memory_resource/synchronized_pool_resource.h @@ -9,20 +9,19 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> #include <__memory_resource/unsynchronized_pool_resource.h> #include -#if !defined(_LIBCPP_HAS_NO_THREADS) -# include -#endif +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -30,7 +29,7 @@ namespace pmr { // [mem.res.pool.overview] -class _LIBCPP_TYPE_VIS synchronized_pool_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI synchronized_pool_resource : public memory_resource { public: _LIBCPP_HIDE_FROM_ABI synchronized_pool_resource(const pool_options& __opts, memory_resource* __upstream) : __unsync_(__opts, __upstream) {} @@ -46,7 +45,7 @@ public: synchronized_pool_resource(const synchronized_pool_resource&) = delete; - ~synchronized_pool_resource() override = default; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~synchronized_pool_resource() override = default; synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; @@ -89,6 +88,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H diff --git a/lib/libcxx/include/__memory_resource/unsynchronized_pool_resource.h b/lib/libcxx/include/__memory_resource/unsynchronized_pool_resource.h index 91d38aac0d..81d5f9ec4d 100644 --- a/lib/libcxx/include/__memory_resource/unsynchronized_pool_resource.h +++ b/lib/libcxx/include/__memory_resource/unsynchronized_pool_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> @@ -19,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -27,7 +28,7 @@ namespace pmr { // [mem.res.pool.overview] -class _LIBCPP_TYPE_VIS unsynchronized_pool_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI unsynchronized_pool_resource : public memory_resource { class __fixed_pool; class __adhoc_pool { @@ -101,6 +102,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H diff --git a/lib/libcxx/include/__mutex/lock_guard.h b/lib/libcxx/include/__mutex/lock_guard.h new file mode 100644 index 0000000000..c075512fb9 --- /dev/null +++ b/lib/libcxx/include/__mutex/lock_guard.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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___MUTEX_LOCK_GUARD_H +#define _LIBCPP___MUTEX_LOCK_GUARD_H + +#include <__config> +#include <__mutex/tag_types.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) lock_guard { +public: + typedef _Mutex mutex_type; + +private: + mutex_type& __m_; + +public: + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) + _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + : __m_(__m) { + __m_.lock(); + } + + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) + _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) + : __m_(__m) {} + _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } + +private: + lock_guard(lock_guard const&) = delete; + lock_guard& operator=(lock_guard const&) = delete; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_LOCK_GUARD_H diff --git a/lib/libcxx/include/__mutex/mutex.h b/lib/libcxx/include/__mutex/mutex.h new file mode 100644 index 0000000000..4423abf62b --- /dev/null +++ b/lib/libcxx/include/__mutex/mutex.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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___MUTEX_MUTEX_H +#define _LIBCPP___MUTEX_MUTEX_H + +#include <__config> +#include <__threading_support> +#include <__type_traits/is_nothrow_default_constructible.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + +# if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) + _LIBCPP_HIDE_FROM_ABI ~mutex() = default; +# else + ~mutex() _NOEXCEPT; +# endif + + void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); + bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); + void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); + + typedef __libcpp_mutex_t* native_handle_type; + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; } +}; + +static_assert(is_nothrow_default_constructible::value, "the default constructor for std::mutex must be nothrow"); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_MUTEX_H diff --git a/lib/libcxx/include/__mutex/tag_types.h b/lib/libcxx/include/__mutex/tag_types.h new file mode 100644 index 0000000000..05ccb8b23a --- /dev/null +++ b/lib/libcxx/include/__mutex/tag_types.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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___MUTEX_TAG_TYPES_H +#define _LIBCPP___MUTEX_TAG_TYPES_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_EXPORTED_FROM_ABI defer_lock_t { + explicit defer_lock_t() = default; +}; + +struct _LIBCPP_EXPORTED_FROM_ABI try_to_lock_t { + explicit try_to_lock_t() = default; +}; + +struct _LIBCPP_EXPORTED_FROM_ABI adopt_lock_t { + explicit adopt_lock_t() = default; +}; + +# if _LIBCPP_STD_VER >= 17 +inline constexpr defer_lock_t defer_lock = defer_lock_t(); +inline constexpr try_to_lock_t try_to_lock = try_to_lock_t(); +inline constexpr adopt_lock_t adopt_lock = adopt_lock_t(); +# elif !defined(_LIBCPP_CXX03_LANG) +constexpr defer_lock_t defer_lock = defer_lock_t(); +constexpr try_to_lock_t try_to_lock = try_to_lock_t(); +constexpr adopt_lock_t adopt_lock = adopt_lock_t(); +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_TAG_TYPES_H diff --git a/lib/libcxx/include/__mutex/unique_lock.h b/lib/libcxx/include/__mutex/unique_lock.h new file mode 100644 index 0000000000..c27ce4b24c --- /dev/null +++ b/lib/libcxx/include/__mutex/unique_lock.h @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// 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___MUTEX_UNIQUE_LOCK_H +#define _LIBCPP___MUTEX_UNIQUE_LOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__memory/addressof.h> +#include <__mutex/tag_types.h> +#include <__system_error/system_error.h> +#include <__utility/swap.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS unique_lock { +public: + typedef _Mutex mutex_type; + +private: + mutex_type* __m_; + bool __owns_; + +public: + _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} + _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) { + __m_->lock(); + } + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + : __m_(std::addressof(__m)), + __owns_(false) {} + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) + : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {} + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {} + + template + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) + : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} + + template + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) + : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} + + _LIBCPP_HIDE_FROM_ABI ~unique_lock() { + if (__owns_) + __m_->unlock(); + } + + unique_lock(unique_lock const&) = delete; + unique_lock& operator=(unique_lock const&) = delete; + + _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { + __u.__m_ = nullptr; + __u.__owns_ = false; + } + + _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { + if (__owns_) + __m_->unlock(); + + __m_ = __u.__m_; + __owns_ = __u.__owns_; + __u.__m_ = nullptr; + __u.__owns_ = false; + return *this; + } + + void lock(); + bool try_lock(); + + template + bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); + + template + bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); + + void unlock(); + + _LIBCPP_HIDE_FROM_ABI void swap(unique_lock& __u) _NOEXCEPT { + std::swap(__m_, __u.__m_); + std::swap(__owns_, __u.__owns_); + } + + _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT { + mutex_type* __m = __m_; + __m_ = nullptr; + __owns_ = false; + return __m; + } + + _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; } + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; } + _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); + +template +void unique_lock<_Mutex>::lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); + __m_->lock(); + __owns_ = true; +} + +template +bool unique_lock<_Mutex>::try_lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); + __owns_ = __m_->try_lock(); + return __owns_; +} + +template +template +bool unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); + __owns_ = __m_->try_lock_for(__d); + return __owns_; +} + +template +template +bool unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); + __owns_ = __m_->try_lock_until(__t); + return __owns_; +} + +template +void unique_lock<_Mutex>::unlock() { + if (!__owns_) + __throw_system_error(EPERM, "unique_lock::unlock: not locked"); + __m_->unlock(); + __owns_ = false; +} + +template +inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT { + __x.swap(__y); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H diff --git a/lib/libcxx/include/__mutex_base b/lib/libcxx/include/__mutex_base deleted file mode 100644 index 82d9fa6ecb..0000000000 --- a/lib/libcxx/include/__mutex_base +++ /dev/null @@ -1,523 +0,0 @@ -// -*- 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___MUTEX_BASE -#define _LIBCPP___MUTEX_BASE - -#include <__chrono/duration.h> -#include <__chrono/steady_clock.h> -#include <__chrono/system_clock.h> -#include <__chrono/time_point.h> -#include <__config> -#include <__threading_support> -#include -#include -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifndef _LIBCPP_HAS_NO_THREADS - -class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex -{ - __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; - -public: - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR mutex() = default; - - mutex(const mutex&) = delete; - mutex& operator=(const mutex&) = delete; - -#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) - ~mutex() = default; -#else - ~mutex() _NOEXCEPT; -#endif - - void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); - bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); - void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); - - typedef __libcpp_mutex_t* native_handle_type; - _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} -}; - -static_assert(is_nothrow_default_constructible::value, - "the default constructor for std::mutex must be nothrow"); - -struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; }; -struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; }; -struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; }; - -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) - -extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; -extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; -extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; - -#else - -/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t(); -/* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); -/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); - -#endif - -template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) -lock_guard -{ -public: - typedef _Mutex mutex_type; - -private: - mutex_type& __m_; -public: - - _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY - explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) - : __m_(__m) {__m_.lock();} - - _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY - lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) - : __m_(__m) {} - _LIBCPP_INLINE_VISIBILITY - ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} - -private: - lock_guard(lock_guard const&) = delete; - lock_guard& operator=(lock_guard const&) = delete; -}; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); - -template -class _LIBCPP_TEMPLATE_VIS unique_lock -{ -public: - typedef _Mutex mutex_type; - -private: - mutex_type* __m_; - bool __owns_; - -public: - _LIBCPP_INLINE_VISIBILITY - unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} - _LIBCPP_INLINE_VISIBILITY - explicit unique_lock(mutex_type& __m) - : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(_VSTD::addressof(__m)), __owns_(false) {} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, try_to_lock_t) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, adopt_lock_t) - : __m_(_VSTD::addressof(__m)), __owns_(true) {} - template - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} - template - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} - _LIBCPP_INLINE_VISIBILITY - ~unique_lock() - { - if (__owns_) - __m_->unlock(); - } - - unique_lock(unique_lock const&) = delete; - unique_lock& operator=(unique_lock const&) = delete; - - _LIBCPP_INLINE_VISIBILITY - unique_lock(unique_lock&& __u) _NOEXCEPT - : __m_(__u.__m_), __owns_(__u.__owns_) - {__u.__m_ = nullptr; __u.__owns_ = false;} - _LIBCPP_INLINE_VISIBILITY - unique_lock& operator=(unique_lock&& __u) _NOEXCEPT - { - if (__owns_) - __m_->unlock(); - __m_ = __u.__m_; - __owns_ = __u.__owns_; - __u.__m_ = nullptr; - __u.__owns_ = false; - return *this; - } - - void lock(); - bool try_lock(); - - template - bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); - template - bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); - - void unlock(); - - _LIBCPP_INLINE_VISIBILITY - void swap(unique_lock& __u) _NOEXCEPT - { - _VSTD::swap(__m_, __u.__m_); - _VSTD::swap(__owns_, __u.__owns_); - } - _LIBCPP_INLINE_VISIBILITY - mutex_type* release() _NOEXCEPT - { - mutex_type* __m = __m_; - __m_ = nullptr; - __owns_ = false; - return __m; - } - - _LIBCPP_INLINE_VISIBILITY - bool owns_lock() const _NOEXCEPT {return __owns_;} - _LIBCPP_INLINE_VISIBILITY - explicit operator bool() const _NOEXCEPT {return __owns_;} - _LIBCPP_INLINE_VISIBILITY - mutex_type* mutex() const _NOEXCEPT {return __m_;} -}; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); - -template -void -unique_lock<_Mutex>::lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); - __m_->lock(); - __owns_ = true; -} - -template -bool -unique_lock<_Mutex>::try_lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); - __owns_ = __m_->try_lock(); - return __owns_; -} - -template -template -bool -unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); - __owns_ = __m_->try_lock_for(__d); - return __owns_; -} - -template -template -bool -unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); - __owns_ = __m_->try_lock_until(__t); - return __owns_; -} - -template -void -unique_lock<_Mutex>::unlock() -{ - if (!__owns_) - __throw_system_error(EPERM, "unique_lock::unlock: not locked"); - __m_->unlock(); - __owns_ = false; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -void -swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT - {__x.swap(__y);} - -//enum class cv_status -_LIBCPP_DECLARE_STRONG_ENUM(cv_status) -{ - no_timeout, - timeout -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) - -class _LIBCPP_TYPE_VIS condition_variable -{ - __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; -public: - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - -#ifdef _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_INLINE_VISIBILITY - wait_for(unique_lock& __lk, - const chrono::duration<_Rep, _Period>& __d, - _Predicate __pred); - - typedef __libcpp_condvar_t* native_handle_type; - _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} - -private: - void __do_timed_wait(unique_lock& __lk, - chrono::time_point) _NOEXCEPT; -#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) - void __do_timed_wait(unique_lock& __lk, - chrono::time_point) _NOEXCEPT; -#endif - template - void __do_timed_wait(unique_lock& __lk, - chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; -}; -#endif // !_LIBCPP_HAS_NO_THREADS - -template -inline _LIBCPP_INLINE_VISIBILITY -__enable_if_t::value, chrono::nanoseconds> -__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) -{ - using namespace chrono; - using __ratio = ratio_divide<_Period, nano>; - using __ns_rep = nanoseconds::rep; - _Rep __result_float = __d.count() * __ratio::num / __ratio::den; - - _Rep __result_max = numeric_limits<__ns_rep>::max(); - if (__result_float >= __result_max) { - return nanoseconds::max(); - } - - _Rep __result_min = numeric_limits<__ns_rep>::min(); - if (__result_float <= __result_min) { - return nanoseconds::min(); - } - - return nanoseconds(static_cast<__ns_rep>(__result_float)); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -__enable_if_t::value, chrono::nanoseconds> -__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) -{ - using namespace chrono; - if (__d.count() == 0) { - return nanoseconds(0); - } - - using __ratio = ratio_divide<_Period, nano>; - using __ns_rep = nanoseconds::rep; - __ns_rep __result_max = numeric_limits<__ns_rep>::max(); - if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { - return nanoseconds::max(); - } - - __ns_rep __result_min = numeric_limits<__ns_rep>::min(); - if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { - return nanoseconds::min(); - } - - __ns_rep __result = __d.count() * __ratio::num / __ratio::den; - if (__result == 0) { - return nanoseconds(1); - } - - return nanoseconds(__result); -} - -#ifndef _LIBCPP_HAS_NO_THREADS -template -void -condition_variable::wait(unique_lock& __lk, _Predicate __pred) -{ - while (!__pred()) - wait(__lk); -} - -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>; - - typename _Clock::time_point __now = _Clock::now(); - if (__t <= __now) - return cv_status::timeout; - - __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__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 defined(_LIBCPP_HAS_COND_CLOCKWAIT) - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); -#else - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); -#endif - - __ns_rep __d_ns_count = _VSTD::__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 -inline -bool -condition_variable::wait_for(unique_lock& __lk, - const chrono::duration<_Rep, _Period>& __d, - _Predicate __pred) -{ - return wait_until(__lk, chrono::steady_clock::now() + __d, - _VSTD::move(__pred)); -} - -#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) -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"); - nanoseconds __d = __tp.time_since_epoch(); - timespec __ts; - seconds __s = duration_cast(__d); - using __ts_sec = decltype(__ts.tv_sec); - const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); - if (__s.count() < __ts_sec_max) - { - __ts.tv_sec = static_cast<__ts_sec>(__s.count()); - __ts.tv_nsec = (__d - __s).count(); - } - else - { - __ts.tv_sec = __ts_sec_max; - __ts.tv_nsec = giga::num - 1; - } - 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"); -} -#endif // _LIBCPP_HAS_COND_CLOCKWAIT - -template -inline -void -condition_variable::__do_timed_wait(unique_lock& __lk, - chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT -{ - wait_for(__lk, __tp - _Clock::now()); -} - -#endif // !_LIBCPP_HAS_NO_THREADS - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___MUTEX_BASE diff --git a/lib/libcxx/include/__node_handle b/lib/libcxx/include/__node_handle index bc49272b9f..cc4eaf73c0 100644 --- a/lib/libcxx/include/__node_handle +++ b/lib/libcxx/include/__node_handle @@ -68,9 +68,12 @@ public: # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // Specialized in __tree & __hash_table for their _NodeType. template @@ -146,7 +149,7 @@ public: _LIBCPP_INLINE_VISIBILITY __basic_node_handle& operator=(__basic_node_handle&& __other) { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_ == _VSTD::nullopt || __alloc_traits::propagate_on_container_move_assignment::value || __alloc_ == __other.__alloc_, @@ -247,8 +250,10 @@ struct _LIBCPP_TEMPLATE_VIS __insert_return_type _NodeType node; }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NODE_HANDLE diff --git a/lib/libcxx/include/__numeric/accumulate.h b/lib/libcxx/include/__numeric/accumulate.h index 81fc0c2943..d75c16ead2 100644 --- a/lib/libcxx/include/__numeric/accumulate.h +++ b/lib/libcxx/include/__numeric/accumulate.h @@ -17,6 +17,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -25,7 +28,7 @@ _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) { for (; __first != __last; ++__first) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = _VSTD::move(__init) + *__first; #else __init = __init + *__first; @@ -39,7 +42,7 @@ _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op) { for (; __first != __last; ++__first) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = __binary_op(_VSTD::move(__init), *__first); #else __init = __binary_op(__init, *__first); @@ -49,4 +52,6 @@ accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOpe _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_ACCUMULATE_H diff --git a/lib/libcxx/include/__numeric/adjacent_difference.h b/lib/libcxx/include/__numeric/adjacent_difference.h index 57e2f5b280..4b06f9f29f 100644 --- a/lib/libcxx/include/__numeric/adjacent_difference.h +++ b/lib/libcxx/include/__numeric/adjacent_difference.h @@ -18,6 +18,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,7 +35,7 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { typename iterator_traits<_InputIterator>::value_type __val(*__first); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 *__result = __val - _VSTD::move(__acc); #else *__result = __val - __acc; @@ -56,7 +59,7 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { typename iterator_traits<_InputIterator>::value_type __val(*__first); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 *__result = __binary_op(__val, _VSTD::move(__acc)); #else *__result = __binary_op(__val, __acc); @@ -69,4 +72,6 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_ADJACENT_DIFFERENCE_H diff --git a/lib/libcxx/include/__numeric/exclusive_scan.h b/lib/libcxx/include/__numeric/exclusive_scan.h index d02e126b53..b6091f153a 100644 --- a/lib/libcxx/include/__numeric/exclusive_scan.h +++ b/lib/libcxx/include/__numeric/exclusive_scan.h @@ -18,9 +18,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator @@ -46,8 +49,10 @@ exclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __ return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>()); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_EXCLUSIVE_SCAN_H diff --git a/lib/libcxx/include/__numeric/gcd_lcm.h b/lib/libcxx/include/__numeric/gcd_lcm.h index 5a3f81b695..1e5ab5713d 100644 --- a/lib/libcxx/include/__numeric/gcd_lcm.h +++ b/lib/libcxx/include/__numeric/gcd_lcm.h @@ -28,7 +28,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template ::value> struct __ct_abs; @@ -87,7 +87,7 @@ lcm(_Tp __m, _Up __n) using _Rp = common_type_t<_Tp,_Up>; _Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n); _Rp __val2 = __ct_abs<_Rp, _Up>()(__n); - _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); + _LIBCPP_ASSERT_UNCATEGORIZED((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); return __val1 * __val2; } diff --git a/lib/libcxx/include/__numeric/inclusive_scan.h b/lib/libcxx/include/__numeric/inclusive_scan.h index e5bf5ac5b7..bd96344602 100644 --- a/lib/libcxx/include/__numeric/inclusive_scan.h +++ b/lib/libcxx/include/__numeric/inclusive_scan.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator @@ -53,7 +53,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inclusiv return _VSTD::inclusive_scan(__first, __last, __result, _VSTD::plus<>()); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__numeric/inner_product.h b/lib/libcxx/include/__numeric/inner_product.h index e3d68c04c2..14144257ea 100644 --- a/lib/libcxx/include/__numeric/inner_product.h +++ b/lib/libcxx/include/__numeric/inner_product.h @@ -17,6 +17,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -25,7 +28,7 @@ _Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init) { for (; __first1 != __last1; ++__first1, (void) ++__first2) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = _VSTD::move(__init) + *__first1 * *__first2; #else __init = __init + *__first1 * *__first2; @@ -40,7 +43,7 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2) { for (; __first1 != __last1; ++__first1, (void) ++__first2) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = __binary_op1(_VSTD::move(__init), __binary_op2(*__first1, *__first2)); #else __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); @@ -50,4 +53,6 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_INNER_PRODUCT_H diff --git a/lib/libcxx/include/__numeric/midpoint.h b/lib/libcxx/include/__numeric/midpoint.h index bac3642cbd..5325f5e6b3 100644 --- a/lib/libcxx/include/__numeric/midpoint.h +++ b/lib/libcxx/include/__numeric/midpoint.h @@ -33,7 +33,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t && !is_same_v && !is_null_pointer_v<_Tp>, _Tp> @@ -86,7 +86,7 @@ midpoint(_Fp __a, _Fp __b) noexcept __a/2 + __b/2; // otherwise correctly rounded } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__numeric/partial_sum.h b/lib/libcxx/include/__numeric/partial_sum.h index 97cca582c0..76349750b6 100644 --- a/lib/libcxx/include/__numeric/partial_sum.h +++ b/lib/libcxx/include/__numeric/partial_sum.h @@ -18,6 +18,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -31,7 +34,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res *__result = __t; for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __t = _VSTD::move(__t) + *__first; #else __t = __t + *__first; @@ -54,7 +57,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res *__result = __t; for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __t = __binary_op(_VSTD::move(__t), *__first); #else __t = __binary_op(__t, *__first); @@ -67,4 +70,6 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_PARTIAL_SUM_H diff --git a/lib/libcxx/include/__numeric/pstl_reduce.h b/lib/libcxx/include/__numeric/pstl_reduce.h new file mode 100644 index 0000000000..163e0078e1 --- /dev/null +++ b/lib/libcxx/include/__numeric/pstl_reduce.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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___NUMERIC_PSTL_REDUCE_H +#define _LIBCPP___NUMERIC_PSTL_REDUCE_H + +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__numeric/pstl_transform_reduce.h> +#include <__type_traits/is_execution_policy.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +void __pstl_reduce(); + +template , + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +reduce(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __op = {}) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Tp __g_init, _BinaryOperation __g_op) { + return std::transform_reduce( + __policy, std::move(__g_first), std::move(__g_last), std::move(__g_init), std::move(__g_op), __identity{}); + }, + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__op)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator> +reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last) { + return std::reduce(__policy, __g_first, __g_last, __iter_value_type<_ForwardIterator>()); + }, + std::move(__first), + std::move(__last)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___NUMERIC_PSTL_REDUCE_H diff --git a/lib/libcxx/include/__numeric/pstl_transform_reduce.h b/lib/libcxx/include/__numeric/pstl_transform_reduce.h new file mode 100644 index 0000000000..b7c9d8d288 --- /dev/null +++ b/lib/libcxx/include/__numeric/pstl_transform_reduce.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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___NUMERIC_PSTL_TRANSFORM_REDUCE_H +#define _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__functional/operations.h> +#include <__numeric/transform_reduce.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform_reduce<_RawPolicy>( + _Backend{}, + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +// This overload doesn't get a customization point because it's trivial to detect (through e.g. +// __is_trivial_plus_operation) when specializing the more general variant, which should always be preferred +template >, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init) { + return std::transform_reduce(__policy, __first1, __last1, __first2, __init, plus{}, multiplies{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform_reduce<_RawPolicy>( + _Backend{}, + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H diff --git a/lib/libcxx/include/__numeric/reduce.h b/lib/libcxx/include/__numeric/reduce.h index b64df05bc8..8daa7cf60e 100644 --- a/lib/libcxx/include/__numeric/reduce.h +++ b/lib/libcxx/include/__numeric/reduce.h @@ -13,6 +13,7 @@ #include <__config> #include <__functional/operations.h> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,12 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b) { for (; __first != __last; ++__first) - __init = __b(__init, *__first); + __init = __b(std::move(__init), *__first); return __init; } diff --git a/lib/libcxx/include/__numeric/transform_exclusive_scan.h b/lib/libcxx/include/__numeric/transform_exclusive_scan.h index afbcdb8db8..3d5574c7d0 100644 --- a/lib/libcxx/include/__numeric/transform_exclusive_scan.h +++ b/lib/libcxx/include/__numeric/transform_exclusive_scan.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template @@ -42,7 +42,7 @@ transform_exclusive_scan(_InputIterator __first, _InputIterator __last, return __result; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__numeric/transform_inclusive_scan.h b/lib/libcxx/include/__numeric/transform_inclusive_scan.h index c050041bc1..ee9168928a 100644 --- a/lib/libcxx/include/__numeric/transform_inclusive_scan.h +++ b/lib/libcxx/include/__numeric/transform_inclusive_scan.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -51,7 +51,7 @@ transform_inclusive_scan(_InputIterator __first, _InputIterator __last, return __result; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__numeric/transform_reduce.h b/lib/libcxx/include/__numeric/transform_reduce.h index d997521a95..7e47f34d37 100644 --- a/lib/libcxx/include/__numeric/transform_reduce.h +++ b/lib/libcxx/include/__numeric/transform_reduce.h @@ -20,13 +20,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b, _UnaryOp __u) { for (; __first != __last; ++__first) - __init = __b(__init, __u(*__first)); + __init = __b(std::move(__init), __u(*__first)); return __init; } @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp transform_reduce(_In _InputIterator2 __first2, _Tp __init, _BinaryOp1 __b1, _BinaryOp2 __b2) { for (; __first1 != __last1; ++__first1, (void)++__first2) - __init = __b1(__init, __b2(*__first1, *__first2)); + __init = __b1(std::move(__init), __b2(*__first1, *__first2)); return __init; } diff --git a/lib/libcxx/include/__pstl/internal/algorithm_fwd.h b/lib/libcxx/include/__pstl/internal/algorithm_fwd.h new file mode 100644 index 0000000000..ba350392c2 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/algorithm_fwd.h @@ -0,0 +1,1768 @@ +// -*- 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 _PSTL_ALGORITHM_FWD_H +#define _PSTL_ALGORITHM_FWD_H + +#include <__config> +#include +#include +#include + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// walk1 (pseudo) +// +// walk1 evaluates f(x) for each dereferenced value x drawn from [first,last) +//------------------------------------------------------------------------ + +template +void __brick_walk1(_ForwardIterator, + _ForwardIterator, + _Function, + /*vector=*/std::false_type) noexcept; + +template +void __brick_walk1(_RandomAccessIterator, + _RandomAccessIterator, + _Function, + /*vector=*/std::true_type) noexcept; + +template +void __pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function) noexcept; + +template +void __pattern_walk1( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Function); + +template +void __pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick) noexcept; + +template +void __pattern_walk_brick( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Brick); + +//------------------------------------------------------------------------ +// walk1_n +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_walk1_n( + _ForwardIterator, + _Size, + _Function, + /*_IsVectorTag=*/std::false_type); + +template +_RandomAccessIterator __brick_walk1_n( + _RandomAccessIterator, + _DifferenceType, + _Function, + /*vectorTag=*/std::true_type) noexcept; + +template +_ForwardIterator __pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Function) noexcept; + +template +_RandomAccessIterator +__pattern_walk1_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function); + +template +_ForwardIterator __pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Brick) noexcept; + +template +_RandomAccessIterator +__pattern_walk_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick); + +//------------------------------------------------------------------------ +// walk2 (pseudo) +// +// walk2 evaluates f(x,y) for deferenced values (x,y) drawn from [first1,last1) and [first2,...) +//------------------------------------------------------------------------ + +template +_ForwardIterator2 __brick_walk2( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _Function, + /*vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator2 __brick_walk2( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Function, + /*vector=*/std::true_type) noexcept; + +template +_ForwardIterator2 __brick_walk2_n( + _ForwardIterator1, + _Size, + _ForwardIterator2, + _Function, + /*vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator2 __brick_walk2_n( + _RandomAccessIterator1, + _Size, + _RandomAccessIterator2, + _Function, + /*vector=*/std::true_type) noexcept; + +template +_ForwardIterator2 +__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function) noexcept; + +template +_RandomAccessIterator2 __pattern_walk2( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Function); + +template +_ForwardIterator2 +__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function) noexcept; + +template +_RandomAccessIterator2 __pattern_walk2_n( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function); + +template +_ForwardIterator2 __pattern_walk2_brick( + _Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Brick) noexcept; + +template +_RandomAccessIterator2 __pattern_walk2_brick( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Brick); + +template +_ForwardIterator2 +__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick) noexcept; + +template +_RandomAccessIterator2 __pattern_walk2_brick_n( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Brick); + +//------------------------------------------------------------------------ +// walk3 (pseudo) +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +template +_ForwardIterator3 __brick_walk3( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator3, + _Function, + /*vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator3 __brick_walk3( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator3, + _Function, + /*vector=*/std::true_type) noexcept; + +template +_ForwardIterator3 __pattern_walk3( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator3, + _Function) noexcept; + +template +_RandomAccessIterator3 __pattern_walk3( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator3, + _Function); + +//------------------------------------------------------------------------ +// equal +//------------------------------------------------------------------------ + +template +bool __brick_equal(_ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _BinaryPredicate, + /* is_vector = */ std::false_type) noexcept; + +template +bool __brick_equal(_RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _BinaryPredicate, + /* is_vector = */ std::true_type) noexcept; + +template +bool __pattern_equal( + _Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _BinaryPredicate) noexcept; + +template +bool __pattern_equal( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _BinaryPredicate); + +template +bool __brick_equal(_ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /* is_vector = */ std::false_type) noexcept; + +template +bool __brick_equal(_RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /* is_vector = */ std::true_type) noexcept; + +template +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template +bool __pattern_equal( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate); + +//------------------------------------------------------------------------ +// find_end +//------------------------------------------------------------------------ + +template +_ForwardIterator1 __brick_find_end( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator1 __brick_find_end( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template +_ForwardIterator1 __pattern_find_end( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template +_RandomAccessIterator1 __pattern_find_end( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// find_first_of +//------------------------------------------------------------------------ + +template +_ForwardIterator1 __brick_find_first_of( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator1 __brick_find_first_of( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template +_ForwardIterator1 __pattern_find_first_of( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template +_RandomAccessIterator1 __pattern_find_first_of( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// search +//------------------------------------------------------------------------ + +template +_ForwardIterator1 __brick_search( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +_ForwardIterator1 __pattern_search( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template +_RandomAccessIterator1 __pattern_search( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// search_n +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_search_n( + _ForwardIterator, + _ForwardIterator, + _Size, + const _Tp&, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator __brick_search_n( + _RandomAccessIterator, + _RandomAccessIterator, + _Size, + const _Tp&, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +_ForwardIterator __pattern_search_n( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate) noexcept; + +template +_RandomAccessIterator __pattern_search_n( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _Size, + const _Tp&, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// copy_n +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_copy_n(_ForwardIterator, + _Size, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_copy_n(_RandomAccessIterator, + _Size, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_copy(_ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_copy(_RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// move +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_move(_ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_move(_RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// swap_ranges +//------------------------------------------------------------------------ +template +_OutputIterator __brick_swap_ranges( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_swap_ranges( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// copy_if +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_copy_if( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryPredicate, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_copy_if( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _ForwardIterator, + _ForwardIterator, + bool* __restrict, + _UnaryPredicate, + /*vector=*/std::false_type) noexcept; +template +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _UnaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +void __brick_copy_by_mask( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + bool*, + /*vector=*/std::false_type) noexcept; + +template +void __brick_copy_by_mask( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + bool* __restrict, + /*vector=*/std::true_type) noexcept; + +template +void __brick_partition_by_mask( + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + bool*, + /*vector=*/std::false_type) noexcept; + +template +void __brick_partition_by_mask( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + bool*, + /*vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_copy_if( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate) noexcept; + +template +_OutputIterator __pattern_copy_if( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryPredicate); + +//------------------------------------------------------------------------ +// count +//------------------------------------------------------------------------ + +template +typename std::iterator_traits<_RandomAccessIterator>::difference_type __brick_count( + _RandomAccessIterator, + _RandomAccessIterator, + _Predicate, + /* is_vector = */ std::true_type) noexcept; + +template +typename std::iterator_traits<_ForwardIterator>::difference_type __brick_count( + _ForwardIterator, + _ForwardIterator, + _Predicate, + /* is_vector = */ std::false_type) noexcept; + +template +typename std::iterator_traits<_ForwardIterator>::difference_type +__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept; + +template +typename std::iterator_traits<_RandomAccessIterator>::difference_type __pattern_count( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Predicate); + +//------------------------------------------------------------------------ +// unique +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_unique( + _ForwardIterator, + _ForwardIterator, + _BinaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator __brick_unique( + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template +_ForwardIterator +__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate) noexcept; + +template +_RandomAccessIterator __pattern_unique( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// unique_copy +//------------------------------------------------------------------------ + +template +OutputIterator __brick_unique_copy( + _ForwardIterator, + _ForwardIterator, + OutputIterator, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_unique_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_unique_copy( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate) noexcept; + +template +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_unique_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryPredicate); + +//------------------------------------------------------------------------ +// reverse +//------------------------------------------------------------------------ + +template +void __brick_reverse(_BidirectionalIterator, + _BidirectionalIterator, + /*__is_vector=*/std::false_type) noexcept; + +template +void __brick_reverse(_RandomAccessIterator, + _RandomAccessIterator, + /*__is_vector=*/std::true_type) noexcept; + +template +void __brick_reverse(_BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + /*is_vector=*/std::false_type) noexcept; + +template +void __brick_reverse(_RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + /*is_vector=*/std::true_type) noexcept; + +template +void __pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator) noexcept; + +template +void __pattern_reverse(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator); + +//------------------------------------------------------------------------ +// reverse_copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_reverse_copy( + _BidirectionalIterator, + _BidirectionalIterator, + _OutputIterator, + /*is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_reverse_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_reverse_copy( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator) noexcept; + +template +_OutputIterator __pattern_reverse_copy( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator); + +//------------------------------------------------------------------------ +// rotate +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_rotate( + _ForwardIterator, + _ForwardIterator, + _ForwardIterator, + /*is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator __brick_rotate( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + /*is_vector=*/std::true_type) noexcept; + +template +_ForwardIterator +__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator) noexcept; + +template +_RandomAccessIterator __pattern_rotate( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator); + +//------------------------------------------------------------------------ +// rotate_copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_rotate_copy( + _ForwardIterator, + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*__is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_rotate_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*__is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_rotate_copy( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator) noexcept; + +template +_OutputIterator __pattern_rotate_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator); + +//------------------------------------------------------------------------ +// is_partitioned +//------------------------------------------------------------------------ + +template +bool __brick_is_partitioned(_ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template +bool __brick_is_partitioned(_RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template +bool __pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template +bool __pattern_is_partitioned( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate); + +//------------------------------------------------------------------------ +// partition +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_partition( + _ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator __brick_partition( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template +_ForwardIterator +__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template +_RandomAccessIterator __pattern_partition( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate); + +//------------------------------------------------------------------------ +// stable_partition +//------------------------------------------------------------------------ + +template +_BidirectionalIterator __brick_stable_partition( + _BidirectionalIterator, + _BidirectionalIterator, + _UnaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template +_RandomAccessIterator __brick_stable_partition( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template +_BidirectionalIterator __pattern_stable_partition( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate) noexcept; + +template +_RandomAccessIterator __pattern_stable_partition( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// partition_copy +//------------------------------------------------------------------------ + +template +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate) noexcept; + +template +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate); + +//------------------------------------------------------------------------ +// sort +//------------------------------------------------------------------------ + +template +void __pattern_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsMoveConstructible) noexcept; + +template +void __pattern_sort(__parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /*is_move_constructible=*/std::true_type); + +//------------------------------------------------------------------------ +// stable_sort +//------------------------------------------------------------------------ + +template +void __pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template +void __pattern_stable_sort( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// partial_sort +//------------------------------------------------------------------------ + +template +void __pattern_partial_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template +void __pattern_partial_sort( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare); + +//------------------------------------------------------------------------ +// partial_sort_copy +//------------------------------------------------------------------------ + +template +_RandomAccessIterator2 __pattern_partial_sort_copy( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare) noexcept; + +template +_RandomAccessIterator2 __pattern_partial_sort_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare); + +//------------------------------------------------------------------------ +// adjacent_find +//------------------------------------------------------------------------ + +template +_RandomAccessIterator __brick_adjacent_find( + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + /* IsVector = */ std::true_type, + bool) noexcept; + +template +_ForwardIterator __brick_adjacent_find( + _ForwardIterator, + _ForwardIterator, + _BinaryPredicate, + /* IsVector = */ std::false_type, + bool) noexcept; + +template +_ForwardIterator +__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, bool) noexcept; + +template +_RandomAccessIterator __pattern_adjacent_find( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + bool); + +//------------------------------------------------------------------------ +// nth_element +//------------------------------------------------------------------------ +template +void __pattern_nth_element( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template +void __pattern_nth_element( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare) noexcept; + +//------------------------------------------------------------------------ +// fill, fill_n +//------------------------------------------------------------------------ +template +void __brick_fill(_RandomAccessIterator, + _RandomAccessIterator, + const _Tp&, + /* __is_vector = */ std::true_type) noexcept; + +template +void __brick_fill(_ForwardIterator, + _ForwardIterator, + const _Tp&, + /* __is_vector = */ std::false_type) noexcept; + +template +void __pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&) noexcept; + +template +_RandomAccessIterator +__pattern_fill(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, const _Tp&); + +template +_RandomAccessIterator +__brick_fill_n(_RandomAccessIterator, + _Size, + const _Tp&, + /* __is_vector = */ std::true_type) noexcept; + +template +_OutputIterator +__brick_fill_n(_OutputIterator, + _Size, + const _Tp&, + /* __is_vector = */ std::false_type) noexcept; + +template +_OutputIterator __pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&) noexcept; + +template +_RandomAccessIterator +__pattern_fill_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, const _Tp&); + +//------------------------------------------------------------------------ +// generate, generate_n +//------------------------------------------------------------------------ + +template +void __brick_generate(_RandomAccessIterator, + _RandomAccessIterator, + _Generator, + /* is_vector = */ std::true_type) noexcept; + +template +void __brick_generate(_ForwardIterator, + _ForwardIterator, + _Generator, + /* is_vector = */ std::false_type) noexcept; + +template +void __pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator) noexcept; + +template +_RandomAccessIterator __pattern_generate( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Generator); + +template +_RandomAccessIterator __brick_generate_n( + _RandomAccessIterator, + Size, + _Generator, + /* is_vector = */ std::true_type) noexcept; + +template +OutputIterator __brick_generate_n( + OutputIterator, + Size, + _Generator, + /* is_vector = */ std::false_type) noexcept; + +template +OutputIterator __pattern_generate_n(_Tag, _ExecutionPolicy&&, OutputIterator, Size, _Generator) noexcept; + +template +_RandomAccessIterator +__pattern_generate_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, Size, _Generator); + +//------------------------------------------------------------------------ +// remove +//------------------------------------------------------------------------ +template +_ForwardIterator __brick_remove_if( + _ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /* __is_vector = */ std::false_type) noexcept; + +template +_RandomAccessIterator __brick_remove_if( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /* __is_vector = */ std::true_type) noexcept; + +template +_ForwardIterator +__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template +_RandomAccessIterator __pattern_remove_if( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// merge +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_merge( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +_OutputIterator __brick_merge( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +_OutputIterator __pattern_merge( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template +_OutputIterator __pattern_merge( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// inplace_merge +//------------------------------------------------------------------------ + +template +void __brick_inplace_merge( + _BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +void __brick_inplace_merge( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +void __pattern_inplace_merge( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + _Compare) noexcept; + +template +void __pattern_inplace_merge( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare); + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +template +bool __pattern_includes( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare) noexcept; + +template +bool __pattern_includes( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare); + +//------------------------------------------------------------------------ +// set_union +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_union( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_set_union( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_set_union( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template +_OutputIterator __pattern_set_union( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_intersection +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_intersection( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_set_intersection( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_set_intersection( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template +_OutputIterator __pattern_set_intersection( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_difference( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_set_difference( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_set_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template +_OutputIterator __pattern_set_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_symmetric_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_symmetric_difference( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template +_OutputIterator __brick_set_symmetric_difference( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template +_OutputIterator __pattern_set_symmetric_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template +_OutputIterator __pattern_set_symmetric_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// is_heap_until +//------------------------------------------------------------------------ + +template +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +_RandomAccessIterator +__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template +_RandomAccessIterator __pattern_is_heap_until( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +//------------------------------------------------------------------------ +// min_element +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_min_element( + _ForwardIterator, + _ForwardIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +_RandomAccessIterator __brick_min_element( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +_ForwardIterator __pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; + +template +_RandomAccessIterator __pattern_min_element( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// minmax_element +//------------------------------------------------------------------------ + +template +std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element( + _ForwardIterator, + _ForwardIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +std::pair<_RandomAccessIterator, _RandomAccessIterator> __brick_minmax_element( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +std::pair<_ForwardIterator, _ForwardIterator> +__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; + +template +std::pair<_RandomAccessIterator, _RandomAccessIterator> __pattern_minmax_element( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// mismatch +//------------------------------------------------------------------------ + +template +std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Predicate, + /* __is_vector = */ std::false_type) noexcept; + +template +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __brick_mismatch( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Predicate, + /* __is_vector = */ std::true_type) noexcept; + +template +std::pair<_ForwardIterator1, _ForwardIterator2> __pattern_mismatch( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Predicate) noexcept; + +template +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __pattern_mismatch( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Predicate) noexcept; + +//------------------------------------------------------------------------ +// lexicographical_compare +//------------------------------------------------------------------------ + +template +bool __brick_lexicographical_compare( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template +bool __brick_lexicographical_compare( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template +bool __pattern_lexicographical_compare( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare) noexcept; + +template +bool __pattern_lexicographical_compare( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare) noexcept; + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_ALGORITHM_FWD_H */ diff --git a/lib/libcxx/include/__pstl/internal/algorithm_impl.h b/lib/libcxx/include/__pstl/internal/algorithm_impl.h new file mode 100644 index 0000000000..72043ebbf7 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/algorithm_impl.h @@ -0,0 +1,4174 @@ +// -*- 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 _PSTL_ALGORITHM_IMPL_H +#define _PSTL_ALGORITHM_IMPL_H + +#include <__assert> +#include <__config> +#include +#include +#include +#include +#include + +#include "execution_impl.h" +#include "memory_impl.h" +#include "parallel_backend.h" +#include "parallel_backend_utils.h" +#include "parallel_impl.h" +#include "unseq_backend_simd.h" + +namespace __pstl { +namespace __internal { + +// [alg.foreach] +// for_each_n with no policy + +template +_ForwardIterator __for_each_n_it_serial(_ForwardIterator __first, _Size __n, _Function __f) { + for (; __n > 0; ++__first, --__n) + __f(__first); + return __first; +} + +//------------------------------------------------------------------------ +// walk1 (pseudo) +// +// walk1 evaluates f(x) for each dereferenced value x drawn from [first,last) +//------------------------------------------------------------------------ +template +void __brick_walk1( + _ForwardIterator __first, _ForwardIterator __last, _Function __f, /*vector=*/std::false_type) noexcept { + std::for_each(__first, __last, __f); +} + +template +void __brick_walk1(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Function __f, + /*vector=*/std::true_type) noexcept { + __unseq_backend::__simd_walk_1(__first, __last - __first, __f); +} + +template +void __pattern_walk1( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f) noexcept { + __internal::__brick_walk1(__first, __last, __f, typename _Tag::__is_vector{}); +} + +template +void __pattern_walk1(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__f](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_walk1(__i, __j, __f, _IsVector{}); + }); + }); +} + +template +void __pattern_walk_brick( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick) noexcept { + __brick(__first, __last); +} + +template +void __pattern_walk_brick( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j); }); + }); +} + +//------------------------------------------------------------------------ +// walk1_n +//------------------------------------------------------------------------ +template +_ForwardIterator __brick_walk1_n(_ForwardIterator __first, _Size __n, _Function __f, /*_IsVectorTag=*/std::false_type) { + return __internal::__for_each_n_it_serial(__first, __n, [&__f](_ForwardIterator __it) { + __f(*__it); + }); // calling serial version +} + +template +_RandomAccessIterator +__brick_walk1_n(_RandomAccessIterator __first, + _DifferenceType __n, + _Function __f, + /*vectorTag=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_1(__first, __n, __f); +} + +template +_ForwardIterator +__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f) noexcept { + return __internal::__brick_walk1_n(__first, __n, __f, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_walk1_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __n, + _Function __f) { + __internal::__pattern_walk1(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f); + + return __first + __n; +} + +template +_ForwardIterator +__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick) noexcept { + return __brick(__first, __n); +} + +template +_RandomAccessIterator __pattern_walk_brick_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __n, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __first + __n, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); }); + return __first + __n; + }); +} + +//------------------------------------------------------------------------ +// walk2 (pseudo) +// +// walk2 evaluates f(x,y) for deferenced values (x,y) drawn from [first1,last1) and [first2,...) +//------------------------------------------------------------------------ +template +_ForwardIterator2 +__brick_walk2(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __first1 != __last1; ++__first1, ++__first2) + __f(*__first1, *__first2); + return __first2; +} + +template +_RandomAccessIterator2 +__brick_walk2(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_2(__first1, __last1 - __first1, __first2, __f); +} + +template +_ForwardIterator2 __brick_walk2_n( + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __n > 0; --__n, ++__first1, ++__first2) + __f(*__first1, *__first2); + return __first2; +} + +template +_RandomAccessIterator2 __brick_walk2_n( + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_2(__first1, __n, __first2, __f); +} + +template +_ForwardIterator2 __pattern_walk2( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Function __f) noexcept { + return __internal::__brick_walk2(__first1, __last1, __first2, __f, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_walk2( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__f, __first1, __first2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, _IsVector{}); + }); + return __first2 + (__last1 - __first1); + }); +} + +template +_ForwardIterator2 __pattern_walk2_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Function __f) noexcept { + return __internal::__brick_walk2_n(__first1, __n, __first2, __f, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_walk2_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Function __f) { + return __internal::__pattern_walk2( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, __first2, __f); +} + +template +_ForwardIterator2 __pattern_walk2_brick( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Brick __brick) noexcept { + return __brick(__first1, __last1, __first2); +} + +template +_RandomAccessIterator2 __pattern_walk2_brick( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __brick(__i, __j, __first2 + (__i - __first1)); + }); + return __first2 + (__last1 - __first1); + }); +} + +template +_ForwardIterator2 __pattern_walk2_brick_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Brick __brick) noexcept { + return __brick(__first1, __n, __first2); +} + +template +_RandomAccessIterator2 __pattern_walk2_brick_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __brick(__i, __j - __i, __first2 + (__i - __first1)); + }); + return __first2 + __n; + }); +} + +//------------------------------------------------------------------------ +// walk3 (pseudo) +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ +template +_ForwardIterator3 __brick_walk3( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator3 __first3, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __first1 != __last1; ++__first1, ++__first2, ++__first3) + __f(*__first1, *__first2, *__first3); + return __first3; +} + +template +_RandomAccessIterator3 __brick_walk3( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator3 __first3, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_3(__first1, __last1 - __first1, __first2, __first3, __f); +} + +template +_ForwardIterator3 __pattern_walk3( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator3 __first3, + _Function __f) noexcept { + return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator3 __pattern_walk3( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator3 __first3, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__f, __first1, __first2, __first3](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __internal::__brick_walk3( + __i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f, _IsVector{}); + }); + return __first3 + (__last1 - __first1); + }); +} + +//------------------------------------------------------------------------ +// equal +//------------------------------------------------------------------------ + +template +bool __brick_equal(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p, + /* IsVector = */ std::false_type) noexcept { + return std::equal(__first1, __last1, __first2, __last2, __p); +} + +template +bool __brick_equal(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _BinaryPredicate __p, + /* is_vector = */ std::true_type) noexcept { + if (__last1 - __first1 != __last2 - __first2) + return false; + + return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; +} + +template +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p) noexcept { + return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, typename _Tag::__is_vector{}); +} + +template +bool __pattern_equal( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _BinaryPredicate __p) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last1 - __first1 != __last2 - __first2) + return false; + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return !__internal::__brick_equal( + __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), __p, _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// equal version for sequences with equal length +//------------------------------------------------------------------------ + +template +bool __brick_equal(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p, + /* IsVector = */ std::false_type) noexcept { + return std::equal(__first1, __last1, __first2, __p); +} + +template +bool __brick_equal(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _BinaryPredicate __p, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; +} + +template +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p) noexcept { + return __internal::__brick_equal(__first1, __last1, __first2, __p, typename _Tag::__is_vector{}); +} + +template +bool __pattern_equal( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _BinaryPredicate __p) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// find_end +//------------------------------------------------------------------------ + +// find the first occurrence of the subsequence [s_first, s_last) +// or the last occurrence of the subsequence in the range [first, last) +// b_first determines what occurrence we want to find (first or last) +template +_RandomAccessIterator1 __find_subrange( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator1 __global_last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + bool __b_first, + _IsVector __is_vector) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _ValueType; + auto __n2 = __s_last - __s_first; + if (__n2 < 1) { + return __b_first ? __first : __last; + } + + auto __n1 = __global_last - __first; + if (__n1 < __n2) { + return __last; + } + + auto __cur = __last; + while (__first != __last && (__global_last - __first >= __n2)) { + // find position of *s_first in [first, last) (it can be start of subsequence) + __first = __internal::__brick_find_if( + __first, __last, __equal_value_by_pred<_ValueType, _BinaryPredicate>(*__s_first, __pred), __is_vector); + + // if position that was found previously is the start of subsequence + // then we can exit the loop (b_first == true) or keep the position + // (b_first == false) + if (__first != __last && (__global_last - __first >= __n2) && + __internal::__brick_equal(__s_first + 1, __s_last, __first + 1, __pred, __is_vector)) { + if (__b_first) { + return __first; + } else { + __cur = __first; + } + } else if (__first == __last) { + break; + } else { + } + + // in case of b_first == false we try to find new start position + // for the next subsequence + ++__first; + } + return __cur; +} + +template +_RandomAccessIterator __find_subrange( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __global_last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + _IsVector __is_vector) noexcept { + if (static_cast<_Size>(__global_last - __first) < __count || __count < 1) { + return __last; // According to the standard last shall be returned when count < 1 + } + + auto __unary_pred = __equal_value_by_pred<_Tp, _BinaryPredicate>(__value, __pred); + while (__first != __last && (static_cast<_Size>(__global_last - __first) >= __count)) { + __first = __internal::__brick_find_if(__first, __last, __unary_pred, __is_vector); + + // check that all of elements in [first+1, first+count) equal to value + if (__first != __last && (static_cast<_Size>(__global_last - __first) >= __count) && + !__internal::__brick_any_of(__first + 1, __first + __count, std::not_fn(__unary_pred), __is_vector)) { + return __first; + } else if (__first == __last) { + break; + } else { + ++__first; + } + } + return __last; +} + +template +_ForwardIterator1 __brick_find_end( + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::find_end(__first, __last, __s_first, __s_last, __pred); +} + +template +_RandomAccessIterator1 __brick_find_end( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + return __find_subrange(__first, __last, __last, __s_first, __s_last, __pred, false, std::true_type()); +} + +template +_ForwardIterator1 __pattern_find_end( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator1 __pattern_find_end( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first == __s_last - __s_first) { + const bool __res = + __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __pred); + return __res ? __first : __last; + } else { + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false, _IsVector{}); + }, + std::greater::difference_type>(), + /*is_first=*/false); + }); + } +} + +//------------------------------------------------------------------------ +// find_first_of +//------------------------------------------------------------------------ +template +_ForwardIterator1 __brick_find_first_of( + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::find_first_of(__first, __last, __s_first, __s_last, __pred); +} + +template +_RandomAccessIterator1 __brick_find_first_of( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_find_first_of(__first, __last, __s_first, __s_last, __pred); +} + +template +_ForwardIterator1 __pattern_find_first_of( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator1 __pattern_find_first_of( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, _IsVector{}); + }, + std::less::difference_type>(), + /*is_first=*/true); + }); +} + +//------------------------------------------------------------------------ +// search +//------------------------------------------------------------------------ +template +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::search(__first, __last, __s_first, __s_last, __pred); +} + +template +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __internal::__find_subrange(__first, __last, __last, __s_first, __s_last, __pred, true, std::true_type()); +} + +template +_ForwardIterator1 __pattern_search( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator1 __pattern_search( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first == __s_last - __s_first) { + const bool __res = + __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __pred); + return __res ? __first : __last; + } else { + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true, _IsVector{}); + }, + std::less::difference_type>(), + /*is_first=*/true); + }); + } +} + +//------------------------------------------------------------------------ +// search_n +//------------------------------------------------------------------------ +template +_ForwardIterator __brick_search_n( + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::search_n(__first, __last, __count, __value, __pred); +} + +template +_RandomAccessIterator __brick_search_n( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __internal::__find_subrange(__first, __last, __last, __count, __value, __pred, std::true_type()); +} + +template +_ForwardIterator __pattern_search_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_search_n(__first, __last, __count, __value, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_search_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (static_cast<_Size>(__last - __first) == __count) { + const bool __result = !__internal::__pattern_any_of( + __tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value, &__pred](const _Tp& __val) { + return !__pred(__val, __value); + }); + return __result ? __first : __last; + } else { + return __internal::__except_handler([&__exec, __first, __last, __count, &__value, __pred]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __count, &__value, __pred](_RandomAccessIterator __i, _RandomAccessIterator __j) { + return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, _IsVector{}); + }, + std::less::difference_type>(), + /*is_first=*/true); + }); + } +} + +//------------------------------------------------------------------------ +// copy_n +//------------------------------------------------------------------------ + +template +_OutputIterator +__brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::false_type) noexcept { + return std::copy_n(__first, __n, __result); +} + +template +_RandomAccessIterator2 +__brick_copy_n(_RandomAccessIterator1 __first, + _Size __n, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __n, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = *__first; + }); +} + +//------------------------------------------------------------------------ +// copy +//------------------------------------------------------------------------ +template +_OutputIterator +__brick_copy(_ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::copy(__first, __last, __result); +} + +template +_RandomAccessIterator2 +__brick_copy(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = *__first; + }); +} + +//------------------------------------------------------------------------ +// move +//------------------------------------------------------------------------ +template +_OutputIterator +__brick_move(_ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::move(__first, __last, __result); +} + +template +_RandomAccessIterator2 +__brick_move(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = std::move(*__first); + }); +} + +struct __brick_move_destroy { + template + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vec*/ std::true_type) const { + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; + + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = std::move(*__first); + (*__first).~_IteratorValueType(); + }); + } + + template + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vec*/ std::false_type) const { + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; + + for (; __first != __last; ++__first, ++__result) { + *__result = std::move(*__first); + (*__first).~_IteratorValueType(); + } + return __result; + } +}; + +//------------------------------------------------------------------------ +// swap_ranges +//------------------------------------------------------------------------ +template +_OutputIterator __brick_swap_ranges( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::swap_ranges(__first, __last, __result); +} + +template +_RandomAccessIterator2 __brick_swap_ranges( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + using std::iter_swap; + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, iter_swap<_RandomAccessIterator1, _RandomAccessIterator2>); +} + +//------------------------------------------------------------------------ +// copy_if +//------------------------------------------------------------------------ +template +_OutputIterator __brick_copy_if( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::copy_if(__first, __last, __result, __pred); +} + +template +_RandomAccessIterator2 __brick_copy_if( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _UnaryPredicate __pred, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_copy_if(__first, __last - __first, __result, __pred); +#else + return std::copy_if(__first, __last, __result, __pred); +#endif +} + +// TODO: Try to use transform_reduce for combining __brick_copy_if_phase1 on IsVector. +template +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _ForwardIterator __first, + _ForwardIterator __last, + bool* __restrict __mask, + _UnaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + auto __count_true = _DifferenceType(0); + auto __size = __last - __first; + + static_assert(__are_random_access_iterators<_ForwardIterator>::value, + "Pattern-brick error. Should be a random access iterator."); + + for (; __first != __last; ++__first, ++__mask) { + *__mask = __pred(*__first); + if (*__mask) { + ++__count_true; + } + } + return std::make_pair(__count_true, __size - __count_true); +} + +template +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __mask, + _UnaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + auto __result = __unseq_backend::__simd_calc_mask_1(__first, __last - __first, __mask, __pred); + return std::make_pair(__result, (__last - __first) - __result); +} + +template +void __brick_copy_by_mask( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + bool* __mask, + _Assigner __assigner, + /*vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__mask) { + if (*__mask) { + __assigner(__first, __result); + ++__result; + } + } +} + +template +void __brick_copy_by_mask( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + bool* __restrict __mask, + _Assigner __assigner, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + __unseq_backend::__simd_copy_by_mask(__first, __last - __first, __result, __mask, __assigner); +#else + __internal::__brick_copy_by_mask(__first, __last, __result, __mask, __assigner, std::false_type()); +#endif +} + +template +void __brick_partition_by_mask( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + bool* __mask, + /*vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__mask) { + if (*__mask) { + *__out_true = *__first; + ++__out_true; + } else { + *__out_false = *__first; + ++__out_false; + } + } +} + +template +void __brick_partition_by_mask( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + bool* __mask, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + __unseq_backend::__simd_partition_by_mask(__first, __last - __first, __out_true, __out_false, __mask); +#else + __internal::__brick_partition_by_mask(__first, __last, __out_true, __out_false, __mask, std::false_type()); +#endif +} + +template +_OutputIterator __pattern_copy_if( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_copy_if(__first, __last, __result, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_copy_if( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(1) < __n) { + __par_backend::__buffer __mask_buf(__n); + return __internal::__except_handler([&__exec, __n, __first, __result, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) + .first; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + __internal::__brick_copy_by_mask( + __first + __i, + __first + (__i + __len), + __result + __initial, + __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); + } + // trivial sequence - use serial algorithm + return __internal::__brick_copy_if(__first, __last, __result, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// count +//------------------------------------------------------------------------ +template +typename std::iterator_traits<_RandomAccessIterator>::difference_type +__brick_count(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Predicate __pred, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_count(__first, __last - __first, __pred); +} + +template +typename std::iterator_traits<_ForwardIterator>::difference_type +__brick_count(_ForwardIterator __first, + _ForwardIterator __last, + _Predicate __pred, + /* is_vector = */ std::false_type) noexcept { + return std::count_if(__first, __last, __pred); +} + +template +typename std::iterator_traits<_ForwardIterator>::difference_type __pattern_count( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) noexcept { + return __internal::__brick_count(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template +typename std::iterator_traits<_RandomAccessIterator>::difference_type __pattern_count( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Predicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + _SizeType(0), + [__pred](_RandomAccessIterator __begin, _RandomAccessIterator __end, _SizeType __value) -> _SizeType { + return __value + __internal::__brick_count(__begin, __end, __pred, _IsVector{}); + }, + std::plus<_SizeType>()); + }); +} + +//------------------------------------------------------------------------ +// unique +//------------------------------------------------------------------------ + +template +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::unique(__first, __last, __pred); +} + +template +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::unique(__first, __last, __pred); +} + +template +_ForwardIterator __pattern_unique( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) noexcept { + return __internal::__brick_unique(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +// That function is shared between two algorithms - remove_if (__pattern_remove_if) and unique (pattern unique). But a +// mask calculation is different. So, a caller passes _CalcMask brick into remove_elements. +template +_ForwardIterator __remove_elements( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _CalcMask __calc_mask) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp; + _DifferenceType __n = __last - __first; + __par_backend::__buffer __mask_buf(__n); + // 1. find a first iterator that should be removed + return __internal::__except_handler([&]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __min = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + _DifferenceType(0), + __n, + __n, + [__first, __mask, &__calc_mask]( + _DifferenceType __i, _DifferenceType __j, _DifferenceType __local_min) -> _DifferenceType { + // Create mask + __calc_mask(__mask + __i, __mask + __j, __first + __i); + + // if minimum was found in a previous range we shouldn't do anymore + if (__local_min < __i) { + return __local_min; + } + // find first iterator that should be removed + bool* __result = __internal::__brick_find_if( + __mask + __i, __mask + __j, [](bool __val) { return !__val; }, _IsVector{}); + if (__result - __mask == __j) { + return __local_min; + } + return std::min(__local_min, _DifferenceType(__result - __mask)); + }, + [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType { + return std::min(__local_min1, __local_min2); + }); + + // No elements to remove - exit + if (__min == __n) { + return __last; + } + __n -= __min; + __first += __min; + + __par_backend::__buffer<_Tp> __buf(__n); + _Tp* __result = __buf.get(); + __mask += __min; + _DifferenceType __m{}; + // 2. Elements that doesn't satisfy pred are moved to result + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [__mask](_DifferenceType __i, _DifferenceType __len) { + return __internal::__brick_count( + __mask + __i, __mask + __i + __len, [](bool __val) { return __val; }, _IsVector{}); + }, + std::plus<_DifferenceType>(), + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { + __internal::__brick_copy_by_mask( + __first + __i, + __first + __i + __len, + __result + __initial, + __mask + __i, + [](_ForwardIterator __x, _Tp* __z) { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + + // 3. Elements from result are moved to [first, last) + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + __m, + [__result, __first](_Tp* __i, _Tp* __j) { + __invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { __brick_move(__i, __j, __first + (__i - __result), _IsVector{}); }, + [&]() { __brick_move_destroy()(__i, __j, __first + (__i - __result), _IsVector{}); }); + }); + return __first + __m; + }); +} + +template +_RandomAccessIterator __pattern_unique( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + if (__first == __last) { + return __last; + } + if (__first + 1 == __last || __first + 2 == __last) { + // Trivial sequence - use serial algorithm + return __internal::__brick_unique(__first, __last, __pred, _IsVector{}); + } + return __internal::__remove_elements( + __tag, + std::forward<_ExecutionPolicy>(__exec), + ++__first, + __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) { + __internal::__brick_walk3( + __b, + __e, + __it - 1, + __it, + [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, + _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// unique_copy +//------------------------------------------------------------------------ + +template +OutputIterator __brick_unique_copy( + _ForwardIterator __first, + _ForwardIterator __last, + OutputIterator __result, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::unique_copy(__first, __last, __result, __pred); +} + +template +_RandomAccessIterator2 __brick_unique_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_unique_copy(__first, __last - __first, __result, __pred); +#else + return std::unique_copy(__first, __last, __result, __pred); +#endif +} + +template +_OutputIterator __pattern_unique_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_unique_copy(__first, __last, __result, __pred, typename _Tag::__is_vector{}); +} + +template +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __restrict __mask, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + _DifferenceType __count = 0; + for (; __first != __last; ++__first, ++__mask) { + *__mask = !__pred(*__first, *(__first - 1)); + __count += *__mask; + } + return __count; +} + +template +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __restrict __mask, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_calc_mask_2(__first, __last - __first, __mask, __pred); +} + +template +_RandomAccessIterator2 __pattern_unique_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _BinaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(2) < __n) { + __par_backend::__buffer __mask_buf(__n); + if (_DifferenceType(2) < __n) { + return __internal::__except_handler([&__exec, __n, __first, __result, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce + _DifferenceType __extra = 0; + if (__i == 0) { + // Special boundary case + __mask[__i] = true; + if (--__len == 0) + return 1; + ++__i; + ++__extra; + } + return __internal::__brick_calc_mask_2<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) + + __extra; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + // Phase 2 is same as for __pattern_copy_if + __internal::__brick_copy_by_mask( + __first + __i, + __first + (__i + __len), + __result + __initial, + __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); + } + } + // trivial sequence - use serial algorithm + return __internal::__brick_unique_copy(__first, __last, __result, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// reverse +//------------------------------------------------------------------------ +template +void __brick_reverse( + _BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::false_type) noexcept { + std::reverse(__first, __last); +} + +template +void __brick_reverse( + _RandomAccessIterator __first, _RandomAccessIterator __last, /*__is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + const auto __n = (__last - __first) / 2; + __unseq_backend::__simd_walk_2( + __first, __n, std::reverse_iterator<_RandomAccessIterator>(__last), [](_ReferenceType __x, _ReferenceType __y) { + using std::swap; + swap(__x, __y); + }); +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template +void __brick_reverse(_BidirectionalIterator __first, + _BidirectionalIterator __last, + _BidirectionalIterator __d_last, + /*is_vector=*/std::false_type) noexcept { + for (--__d_last; __first != __last; ++__first, --__d_last) { + using std::iter_swap; + iter_swap(__first, __d_last); + } +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template +void __brick_reverse(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __d_last, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + __unseq_backend::__simd_walk_2( + __first, + __last - __first, + std::reverse_iterator<_RandomAccessIterator>(__d_last), + [](_ReferenceType __x, _ReferenceType __y) { + using std::swap; + swap(__x, __y); + }); +} + +template +void __pattern_reverse( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last) noexcept { + __internal::__brick_reverse(__first, __last, typename _Tag::__is_vector{}); +} + +template +void __pattern_reverse(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __first + (__last - __first) / 2, + [__first, __last](_RandomAccessIterator __inner_first, _RandomAccessIterator __inner_last) { + __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// reverse_copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_reverse_copy( + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _OutputIterator __d_first, + /*is_vector=*/std::false_type) noexcept { + return std::reverse_copy(__first, __last, __d_first); +} + +template +_RandomAccessIterator2 __brick_reverse_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + return __unseq_backend::__simd_walk_2( + std::reverse_iterator<_RandomAccessIterator1>(__last), + __last - __first, + __d_first, + [](_ReferenceType1 __x, _ReferenceType2 __y) { __y = __x; }); +} + +template +_OutputIterator __pattern_reverse_copy( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _OutputIterator __d_first) noexcept { + return __internal::__brick_reverse_copy(__first, __last, __d_first, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_reverse_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + auto __len = __last - __first; + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __len, __d_first](_RandomAccessIterator1 __inner_first, _RandomAccessIterator1 __inner_last) { + __internal::__brick_reverse_copy( + __inner_first, __inner_last, __d_first + (__len - (__inner_last - __first)), _IsVector{}); + }); + return __d_first + __len; +} + +//------------------------------------------------------------------------ +// rotate +//------------------------------------------------------------------------ +template +_ForwardIterator +__brick_rotate(_ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + /*is_vector=*/std::false_type) noexcept { +#if defined(_PSTL_CPP11_STD_ROTATE_BROKEN) + std::rotate(__first, __middle, __last); + return std::next(__first, std::distance(__middle, __last)); +#else + return std::rotate(__first, __middle, __last); +#endif +} + +template +_RandomAccessIterator +__brick_rotate(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + /*is_vector=*/std::true_type) noexcept { + auto __n = __last - __first; + auto __m = __middle - __first; + const _RandomAccessIterator __ret = __first + (__last - __middle); + + bool __is_left = (__m <= __n / 2); + if (!__is_left) + __m = __n - __m; + + while (__n > 1 && __m > 0) { + using std::iter_swap; + const auto __m_2 = __m * 2; + if (__is_left) { + for (; __last - __first >= __m_2; __first += __m) { + __unseq_backend::__simd_assign( + __first, __m, __first + __m, iter_swap<_RandomAccessIterator, _RandomAccessIterator>); + } + } else { + for (; __last - __first >= __m_2; __last -= __m) { + __unseq_backend::__simd_assign( + __last - __m, __m, __last - __m_2, iter_swap<_RandomAccessIterator, _RandomAccessIterator>); + } + } + __is_left = !__is_left; + __m = __n % __m; + __n = __last - __first; + } + + return __ret; +} + +template +_ForwardIterator __pattern_rotate( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) noexcept { + return __internal::__brick_rotate(__first, __middle, __last, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_rotate( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + auto __n = __last - __first; + auto __m = __middle - __first; + if (__m <= __n / 2) { + __par_backend::__buffer<_Tp> __buf(__n - __m); + return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, &__buf]() { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __middle, + __last, + [__middle, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + [__last, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_move(__b, __e, __b + (__last - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + (__n - __m), + [__first, __result](_Tp* __b, _Tp* __e) { + __brick_move_destroy()(__b, __e, __first + (__b - __result), _IsVector{}); + }); + + return __first + (__last - __middle); + }); + } else { + __par_backend::__buffer<_Tp> __buf(__m); + return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, &__buf]() { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + [__first, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __first), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __middle, + __last, + [__first, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_move(__b, __e, __first + (__b - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + __m, + [__n, __m, __first, __result](_Tp* __b, _Tp* __e) { + __brick_move_destroy()(__b, __e, __first + ((__n - __m) + (__b - __result)), _IsVector{}); + }); + + return __first + (__last - __middle); + }); + } +} + +//------------------------------------------------------------------------ +// rotate_copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_rotate_copy( + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _OutputIterator __result, + /*__is_vector=*/std::false_type) noexcept { + return std::rotate_copy(__first, __middle, __last, __result); +} + +template +_RandomAccessIterator2 __brick_rotate_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __middle, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*__is_vector=*/std::true_type) noexcept { + _RandomAccessIterator2 __res = __internal::__brick_copy(__middle, __last, __result, std::true_type()); + return __internal::__brick_copy(__first, __middle, __res, std::true_type()); +} + +template +_OutputIterator __pattern_rotate_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _OutputIterator __result) noexcept { + return __internal::__brick_rotate_copy(__first, __middle, __last, __result, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_rotate_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __middle, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __last, __middle, __result](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) { + if (__b > __middle) { + __internal::__brick_copy(__b, __e, __result + (__b - __middle), _IsVector{}); + } else { + _RandomAccessIterator2 __new_result = __result + ((__last - __middle) + (__b - __first)); + if (__e < __middle) { + __internal::__brick_copy(__b, __e, __new_result, _IsVector{}); + } else { + __internal::__brick_copy(__b, __middle, __new_result, _IsVector{}); + __internal::__brick_copy(__middle, __e, __result, _IsVector{}); + } + } + }); + return __result + (__last - __first); +} + +//------------------------------------------------------------------------ +// is_partitioned +//------------------------------------------------------------------------ + +template +bool __brick_is_partitioned(_ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::is_partitioned(__first, __last, __pred); +} + +template +bool __brick_is_partitioned(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + if (__first == __last) { + return true; + } else { + _RandomAccessIterator __result = __unseq_backend::__simd_first( + __first, _SizeType(0), __last - __first, [&__pred](_RandomAccessIterator __it, _SizeType __i) { + return !__pred(__it[__i]); + }); + if (__result == __last) { + return true; + } else { + ++__result; + return !__unseq_backend::__simd_or(__result, __last - __result, __pred); + } + } +} + +template +bool __pattern_is_partitioned( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_is_partitioned(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template +bool __pattern_is_partitioned( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) { + if (__first == __last) { + return true; + } else { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + // State of current range: + // broken - current range is not partitioned by pred + // all_true - all elements in current range satisfy pred + // all_false - all elements in current range don't satisfy pred + // true_false - elements satisfy pred are placed before elements that don't satisfy pred + enum _ReduceType { __not_init = -1, __broken, __all_true, __all_false, __true_false }; + _ReduceType __init = __not_init; + + // Array with states that we'll have when state from the left branch is merged with state from the right branch. + // State is calculated by formula: new_state = table[left_state * 4 + right_state] + _ReduceType __table[] = { + __broken, + __broken, + __broken, + __broken, + __broken, + __all_true, + __true_false, + __true_false, + __broken, + __broken, + __all_false, + __broken, + __broken, + __broken, + __true_false, + __broken}; + + __init = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [&__pred, + &__table](_RandomAccessIterator __i, _RandomAccessIterator __j, _ReduceType __value) -> _ReduceType { + if (__value == __broken) { + return __broken; + } + _ReduceType __res = __not_init; + // if first element satisfy pred + if (__pred(*__i)) { + // find first element that don't satisfy pred + _RandomAccessIterator __x = __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), _IsVector{}); + if (__x != __j) { + // find first element after "x" that satisfy pred + _RandomAccessIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, _IsVector{}); + // if it was found then range isn't partitioned by pred + if (__y != __j) { + return __broken; + } else { + __res = __true_false; + } + } else { + __res = __all_true; + } + } else { // if first element doesn't satisfy pred + // then we should find the first element that satisfy pred. + // If we found it then range isn't partitioned by pred + if (__internal::__brick_find_if(__i + 1, __j, __pred, _IsVector{}) != __j) { + return __broken; + } else { + __res = __all_false; + } + } + // if we have value from left range then we should calculate the result + return (__value == -1) ? __res : __table[__value * 4 + __res]; + }, + + [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType { + if (__val1 == __broken || __val2 == __broken) { + return __broken; + } + // calculate the result for new big range + return __table[__val1 * 4 + __val2]; + }); + return __init != __broken; + }); + } +} + +//------------------------------------------------------------------------ +// partition +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_partition( + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::partition(__first, __last, __pred); +} + +template +_RandomAccessIterator __brick_partition( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::partition(__first, __last, __pred); +} + +template +_ForwardIterator __pattern_partition( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_partition(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_partition( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct _PartitionRange { + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; + }; + + return __internal::__except_handler([&]() { + _PartitionRange __init{__last, __last, __last}; + + // lambda for merging two partitioned ranges to one partitioned range + auto __reductor = [&__exec](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __size1 = __val1.__end - __val1.__pivot; + auto __size2 = __val2.__pivot - __val2.__begin; + auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (__val1.__end == __val1.__pivot) { + return {__new_begin, __val2.__pivot, __val2.__end}; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else if (__size2 > __size1) { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __val1.__pivot, + __val1.__pivot + __size1, + [__val1, __val2, __size1](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_swap_ranges( + __i, __j, (__val2.__pivot - __size1) + (__i - __val1.__pivot), _IsVector{}); + }); + return {__new_begin, __val2.__pivot - __size1, __val2.__end}; + } + // else we should swap the first part of false part of left range and true part of right range + else { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __val1.__pivot, + __val1.__pivot + __size2, + [__val1, __val2](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), _IsVector{}); + }); + return {__new_begin, __val1.__pivot + __size2, __val2.__end}; + } + }; + + _PartitionRange __result = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [__pred, + __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, _PartitionRange __value) -> _PartitionRange { + // 1. serial partition + _RandomAccessIterator __pivot = __internal::__brick_partition(__i, __j, __pred, _IsVector{}); + + // 2. merging of two ranges (left and right respectively) + return __reductor(__value, {__i, __pivot, __j}); + }, + __reductor); + return __result.__pivot; + }); +} + +//------------------------------------------------------------------------ +// stable_partition +//------------------------------------------------------------------------ + +template +_BidirectionalIterator __brick_stable_partition( + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _UnaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::stable_partition(__first, __last, __pred); +} + +template +_RandomAccessIterator __brick_stable_partition( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::stable_partition(__first, __last, __pred); +} + +template +_BidirectionalIterator __pattern_stable_partition( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_stable_partition(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_stable_partition( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct _PartitionRange { + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; + }; + + return __internal::__except_handler([&]() { + _PartitionRange __init{__last, __last, __last}; + + // lambda for merging two partitioned ranges to one partitioned range + auto __reductor = [](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __size1 = __val1.__end - __val1.__pivot; + auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (__val1.__end == __val1.__pivot) { + return {__new_begin, __val2.__pivot, __val2.__end}; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else { + __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, _IsVector{}); + return {__new_begin, __val2.__pivot - __size1, __val2.__end}; + } + }; + + _PartitionRange __result = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [&__pred, + __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, _PartitionRange __value) -> _PartitionRange { + // 1. serial stable_partition + _RandomAccessIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, _IsVector{}); + + // 2. merging of two ranges (left and right respectively) + return __reductor(__value, {__i, __pivot, __j}); + }, + __reductor); + return __result.__pivot; + }); +} + +//------------------------------------------------------------------------ +// partition_copy +//------------------------------------------------------------------------ + +template +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::partition_copy(__first, __last, __out_true, __out_false, __pred); +} + +template +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> __brick_partition_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_partition_copy(__first, __last - __first, __out_true, __out_false, __pred); +#else + return std::partition_copy(__first, __last, __out_true, __out_false, __pred); +#endif +} + +template +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_partition_copy( + __first, __last, __out_true, __out_false, __pred, typename _Tag::__is_vector{}); +} + +template +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> __pattern_partition_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + typedef std::pair<_DifferenceType, _DifferenceType> _ReturnType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(1) < __n) { + __par_backend::__buffer __mask_buf(__n); + return __internal::__except_handler([&__exec, __n, __first, __out_true, __out_false, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _ReturnType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + std::make_pair(_DifferenceType(0), _DifferenceType(0)), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}); + }, + [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType { + return std::make_pair(__x.first + __y.first, __x.second + __y.second); + }, // Combine + [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan + __internal::__brick_partition_by_mask( + __first + __i, + __first + (__i + __len), + __out_true + __initial.first, + __out_false + __initial.second, + __mask + __i, + _IsVector{}); + }, + [&__m](_ReturnType __total) { __m = __total; }); + return std::make_pair(__out_true + __m.first, __out_false + __m.second); + }); + } + // trivial sequence - use serial algorithm + return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// sort +//------------------------------------------------------------------------ + +template +void __pattern_sort(_Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + _IsMoveConstructible) noexcept { + std::sort(__first, __last, __comp); +} + +template +void __pattern_sort(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /*is_move_constructible=*/std::true_type) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::sort(__first, __last, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// stable_sort +//------------------------------------------------------------------------ + +template +void __pattern_stable_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) noexcept { + std::stable_sort(__first, __last, __comp); +} + +template +void __pattern_stable_sort( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::stable_sort(__first, __last, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// partial_sort +//------------------------------------------------------------------------ + +template +void __pattern_partial_sort( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + std::partial_sort(__first, __middle, __last, __comp); +} + +template +void __pattern_partial_sort( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + const auto __n = __middle - __first; + if (__n == 0) + return; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) { + if (__n < __end - __begin) + std::partial_sort(__begin, __begin + __n, __end, __comp); + else + std::sort(__begin, __end, __comp); + }, + __n); + }); +} + +//------------------------------------------------------------------------ +// partial_sort_copy +//------------------------------------------------------------------------ + +template +_RandomAccessIterator __pattern_partial_sort_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp) noexcept { + return std::partial_sort_copy(__first, __last, __d_first, __d_last, __comp); +} + +template +_RandomAccessIterator2 __pattern_partial_sort_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + _RandomAccessIterator2 __d_last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last == __first || __d_last == __d_first) { + return __d_first; + } + auto __n1 = __last - __first; + auto __n2 = __d_last - __d_first; + return __internal::__except_handler([&]() { + if (__n2 >= __n1) { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __d_first, + __d_first + __n1, + __comp, + [__first, __d_first](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j, _Compare __comp) { + _RandomAccessIterator1 __i1 = __first + (__i - __d_first); + _RandomAccessIterator1 __j1 = __first + (__j - __d_first); + + // 1. Copy elements from input to output +#if !defined(_PSTL_ICC_18_OMP_SIMD_BROKEN) + __internal::__brick_copy(__i1, __j1, __i, _IsVector{}); +#else + std::copy(__i1, __j1, __i); +#endif + // 2. Sort elements in output sequence + std::sort(__i, __j, __comp); + }, + __n1); + return __d_first + __n1; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _T1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _T2; + __par_backend::__buffer<_T1> __buf(__n1); + _T1* __r = __buf.get(); + + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __r, + __r + __n1, + __comp, + [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) { + _RandomAccessIterator1 __it = __first + (__i - __r); + + // 1. Copy elements from input to raw memory + for (_T1* __k = __i; __k != __j; ++__k, ++__it) { + ::new (__k) _T2(*__it); + } + + // 2. Sort elements in temporary __buffer + if (__n2 < __j - __i) + std::partial_sort(__i, __i + __n2, __j, __comp); + else + std::sort(__i, __j, __comp); + }, + __n2); + + // 3. Move elements from temporary __buffer to output + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __r, + __r + __n2, + [__r, __d_first](_T1* __i, _T1* __j) { + __brick_move_destroy()(__i, __j, __d_first + (__i - __r), _IsVector{}); + }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r + __n2, __r + __n1, [](_T1* __i, _T1* __j) { + __brick_destroy(__i, __j, _IsVector{}); + }); + + return __d_first + __n2; + } + }); +} + +//------------------------------------------------------------------------ +// adjacent_find +//------------------------------------------------------------------------ +template +_RandomAccessIterator __brick_adjacent_find( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /* IsVector = */ std::true_type, + bool __or_semantic) noexcept { + return __unseq_backend::__simd_adjacent_find(__first, __last, __pred, __or_semantic); +} + +template +_ForwardIterator __brick_adjacent_find( + _ForwardIterator __first, + _ForwardIterator __last, + _BinaryPredicate __pred, + /* IsVector = */ std::false_type, + bool) noexcept { + return std::adjacent_find(__first, __last, __pred); +} + +template +_ForwardIterator __pattern_adjacent_find( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _BinaryPredicate __pred, + bool __or_semantic) noexcept { + return __internal::__brick_adjacent_find(__first, __last, __pred, typename _Tag::__is_vector{}, __or_semantic); +} + +template +_RandomAccessIterator __pattern_adjacent_find( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + bool __or_semantic) { + if (__last - __first < 2) + return __last; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __last, + [__last, __pred, __or_semantic]( + _RandomAccessIterator __begin, _RandomAccessIterator __end, _RandomAccessIterator __value) + -> _RandomAccessIterator { + // TODO: investigate performance benefits from the use of shared variable for the result, + // checking (compare_and_swap idiom) its __value at __first. + if (__or_semantic && __value < __last) { // found + __par_backend::__cancel_execution(); + return __value; + } + + if (__value > __begin) { + // modify __end to check the predicate on the boundary __values; + // TODO: to use a custom range with boundaries overlapping + // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1) + // then check the pair [__last-1, __last) + if (__end != __last) + ++__end; + + // correct the global result iterator if the "brick" returns a local "__last" + const _RandomAccessIterator __res = + __internal::__brick_adjacent_find(__begin, __end, __pred, _IsVector{}, __or_semantic); + if (__res < __end) + __value = __res; + } + return __value; + }, + [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator { + return __x < __y ? __x : __y; + } // reduce a __value + ); + }); +} + +//------------------------------------------------------------------------ +// nth_element +//------------------------------------------------------------------------ + +template +void __pattern_nth_element( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + std::nth_element(__first, __nth, __last, __comp); +} + +template +void __pattern_nth_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + if (__first == __last || __nth == __last) { + return; + } + + using std::iter_swap; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + _RandomAccessIterator __x; + do { + __x = __internal::__pattern_partition( + __tag, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, [&__comp, __first](const _Tp& __x) { + return __comp(__x, *__first); + }); + --__x; + if (__x != __first) { + iter_swap(__first, __x); + } + // if x > nth then our new range for partition is [first, x) + if (__x - __nth > 0) { + __last = __x; + } + // if x < nth then our new range for partition is [x, last) + else if (__x - __nth < 0) { + // if *x == *nth then we can start new partition with x+1 + if (!__comp(*__nth, *__x) && !__comp(*__x, *__nth)) { + ++__x; + } else { + iter_swap(__nth, __x); + } + __first = __x; + } + } while (__x != __nth); +} + +//------------------------------------------------------------------------ +// generate, generate_n +//------------------------------------------------------------------------ +template +void __brick_generate(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Generator __g, + /* is_vector = */ std::true_type) noexcept { + __unseq_backend::__simd_generate_n(__first, __last - __first, __g); +} + +template +void __brick_generate(_ForwardIterator __first, + _ForwardIterator __last, + _Generator __g, + /* is_vector = */ std::false_type) noexcept { + std::generate(__first, __last, __g); +} + +template +void __pattern_generate( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) noexcept { + __internal::__brick_generate(__first, __last, __g, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_generate( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Generator __g) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__g](_RandomAccessIterator __begin, _RandomAccessIterator __end) { + __internal::__brick_generate(__begin, __end, __g, _IsVector{}); + }); + return __last; + }); +} + +template +_RandomAccessIterator __brick_generate_n( + _RandomAccessIterator __first, + Size __count, + _Generator __g, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_generate_n(__first, __count, __g); +} + +template +OutputIterator +__brick_generate_n(OutputIterator __first, Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept { + return std::generate_n(__first, __count, __g); +} + +template +_OutputIterator +__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g) noexcept { + return __internal::__brick_generate_n(__first, __count, __g, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_generate_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __count, + _Generator __g) { + static_assert(__are_random_access_iterators<_RandomAccessIterator>::value, + "Pattern-brick error. Should be a random access iterator."); + return __internal::__pattern_generate(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __g); +} + +//------------------------------------------------------------------------ +// remove +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_remove_if( + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /* __is_vector = */ std::false_type) noexcept { + return std::remove_if(__first, __last, __pred); +} + +template +_RandomAccessIterator __brick_remove_if( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_remove_if(__first, __last - __first, __pred); +#else + return std::remove_if(__first, __last, __pred); +#endif +} + +template +_ForwardIterator __pattern_remove_if( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_remove_if(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_remove_if( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + if (__first == __last || __first + 1 == __last) { + // Trivial sequence - use serial algorithm + return __internal::__brick_remove_if(__first, __last, __pred, _IsVector{}); + } + + return __internal::__remove_elements( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) { + __internal::__brick_walk2( + __b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); }, _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// inplace_merge +//------------------------------------------------------------------------ +template +void __brick_inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + std::inplace_merge(__first, __middle, __last, __comp); +} + +template +void __brick_inplace_merge( + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + // TODO: vectorize + std::inplace_merge(__first, __middle, __last, __comp); +} + +template +void __pattern_inplace_merge( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) noexcept { + __internal::__brick_inplace_merge(__first, __middle, __last, __comp, typename _Tag::__is_vector{}); +} + +template +void __pattern_inplace_merge( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first == __last || __first == __middle || __middle == __last) { + return; + } + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + auto __n = __last - __first; + __par_backend::__buffer<_Tp> __buf(__n); + _Tp* __r = __buf.get(); + __internal::__except_handler([&]() { + auto __move_values = [](_RandomAccessIterator __x, _Tp* __z) { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + }; + + auto __move_sequences = [](_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Tp* __first2) { + return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector()); + }; + + __par_backend::__parallel_merge( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + __middle, + __last, + __r, + __comp, + [__n, __move_values, __move_sequences]( + _RandomAccessIterator __f1, + _RandomAccessIterator __l1, + _RandomAccessIterator __f2, + _RandomAccessIterator __l2, + _Tp* __f3, + _Compare __comp) { + (__utils::__serial_move_merge(__n))( + __f1, __l1, __f2, __l2, __f3, __comp, __move_values, __move_values, __move_sequences, __move_sequences); + return __f3 + (__l1 - __f1) + (__l2 - __f2); + }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n, [__r, __first](_Tp* __i, _Tp* __j) { + __brick_move_destroy()(__i, __j, __first + (__i - __r), _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +template +bool __pattern_includes( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) noexcept { + return std::includes(__first1, __last1, __first2, __last2, __comp); +} + +template +bool __pattern_includes( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first2 >= __last2) + return true; + + if (__first1 >= __last1 || __comp(*__first2, *__first1) || __comp(*(__last1 - 1), *(__last2 - 1))) + return false; + + __first1 = std::lower_bound(__first1, __last1, *__first2, __comp); + if (__first1 == __last1) + return false; + + if (__last2 - __first2 == 1) + return !__comp(*__first1, *__first2) && !__comp(*__first2, *__first1); + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first2, + __last2, + [__first1, __last1, __first2, __last2, &__comp](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j) { + _LIBCPP_ASSERT_UNCATEGORIZED(__j > __i, ""); + //_LIBCPP_ASSERT_UNCATEGORIZED(__j - __i > 1, ""); + + // 1. moving boundaries to "consume" subsequence of equal elements + auto __is_equal = [&__comp](_RandomAccessIterator2 __a, _RandomAccessIterator2 __b) -> bool { + return !__comp(*__a, *__b) && !__comp(*__b, *__a); + }; + + // 1.1 left bound, case "aaa[aaaxyz...]" - searching "x" + if (__i > __first2 && __is_equal(__i, __i - 1)) { + // whole subrange continues to content equal elements - return "no op" + if (__is_equal(__i, __j - 1)) + return false; + + __i = std::upper_bound(__i, __last2, *__i, __comp); + } + + // 1.2 right bound, case "[...aaa]aaaxyz" - searching "x" + if (__j < __last2 && __is_equal(__j - 1, __j)) + __j = std::upper_bound(__j, __last2, *__j, __comp); + + // 2. testing is __a subsequence of the second range included into the first range + auto __b = std::lower_bound(__first1, __last1, *__i, __comp); + + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(*(__last1 - 1), *__b), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(*(__j - 1), *__i), ""); + return !std::includes(__b, __last1, __i, __j, __comp); + }); + }); +} + +constexpr auto __set_algo_cut_off = 1000; + +template +_OutputIterator __parallel_set_op( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + _SizeFunction __size_func, + _SetOP __set_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; + + struct _SetRange { + _DifferenceType __pos, __len, __buf_pos; + bool empty() const { return __len == 0; } + }; + + const _DifferenceType __n1 = __last1 - __first1; + const _DifferenceType __n2 = __last2 - __first2; + + __par_backend::__buffer<_Tp> __buf(__size_func(__n1, __n2)); + + return __internal::__except_handler( + [&__exec, __n1, __first1, __last1, __first2, __last2, __result, __comp, __size_func, __set_op, &__buf]() { + auto __buffer = __buf.get(); + _DifferenceType __m{}; + auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan + if (!__s.empty()) + __brick_move_destroy()( + __buffer + __s.__buf_pos, __buffer + (__s.__buf_pos + __s.__len), __result + __s.__pos, _IsVector{}); + }; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n1, + _SetRange{0, 0, 0}, //-1, 0}, + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + //[__b; __e) - a subrange of the first sequence, to reduce + _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len); + + // try searching for the first element which not equal to *__b + if (__b != __first1) + __b = std::upper_bound(__b, __last1, *__b, __comp); + + // try searching for the first element which not equal to *__e + if (__e != __last1) + __e = std::upper_bound(__e, __last1, *__e, __comp); + + // check is [__b; __e) empty + if (__e - __b < 1) { + _ForwardIterator2 __bb = __last2; + if (__b != __last1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); + + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + return _SetRange{0, 0, __buf_pos}; + } + + // try searching for "corresponding" subrange [__bb; __ee) in the second sequence + _ForwardIterator2 __bb = __first2; + if (__b != __first1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); + + _ForwardIterator2 __ee = __last2; + if (__e != __last1) + __ee = std::lower_bound(__bb, __last2, *__e, __comp); + + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + auto __buffer_b = __buffer + __buf_pos; + auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp); + + return _SetRange{0, __res - __buffer_b, __buf_pos}; + }, + [](const _SetRange& __a, const _SetRange& __b) { // Combine + if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty())) + return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos}; + return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos}; + }, + __scan, // Scan + [&__m, &__scan](const _SetRange& __total) { // Apex + // final scan + __scan(0, 0, __total); + __m = __total.__pos + __total.__len; + }); + return __result + __m; + }); +} + +// a shared parallel pattern for '__pattern_set_union' and '__pattern_set_symmetric_difference' +template +_OutputIterator __parallel_set_union_op( + _Tag __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + _SetUnionOp __set_union_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + auto copy_range1 = [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { + return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); + }; + auto copy_range2 = [](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) { + return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); + }; + + // {1} {}: parallel copying just first sequence + if (__n2 == 0) + return __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, copy_range1); + + // {} {2}: parallel copying justmake second sequence + if (__n1 == 0) + return __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, copy_range2); + + // testing whether the sequences are intersected + _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + + if (__left_bound_seq_1 == __last1) { + //{1} < {2}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, copy_range1); + }, + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result + __n1, copy_range2); + }); + return __result + __n1 + __n2; + } + + // testing whether the sequences are intersected + _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + + if (__left_bound_seq_2 == __last2) { + //{2} < {1}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, copy_range2); + }, + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result + __n2, copy_range1); + }); + return __result + __n1 + __n2; + } + + const auto __m1 = __left_bound_seq_1 - __first1; + if (__m1 > __set_algo_cut_off) { + auto __res_or = __result; + __result += __m1; // we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + // do parallel copying of [first1; left_bound_seq_1) + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __left_bound_seq_1, __res_or, copy_range1); + }, + [=, &__result] { + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __left_bound_seq_1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); + }); + return __result; + } + + const auto __m2 = __left_bound_seq_2 - __first2; + _LIBCPP_ASSERT_UNCATEGORIZED(__m1 == 0 || __m2 == 0, ""); + if (__m2 > __set_algo_cut_off) { + auto __res_or = __result; + __result += __m2; // we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + // do parallel copying of [first2; left_bound_seq_2) + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __left_bound_seq_2, __res_or, copy_range2); + }, + [=, &__result] { + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __left_bound_seq_2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); + }); + return __result; + } + + return __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); +} + +//------------------------------------------------------------------------ +// set_union +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_union( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +struct __BrickCopyConstruct { + template + _OutputIterator operator()(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result) { + return __brick_uninitialized_copy(__first, __last, __result, _IsVector()); + } +}; + +template +_OutputIterator __brick_set_union( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_OutputIterator __pattern_set_union( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_union( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template +_OutputIterator __pattern_set_union( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // use serial algorithm + if (__n1 + __n2 <= __set_algo_cut_off) + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); + + typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; + return __parallel_set_union_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_union_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); +} + +//------------------------------------------------------------------------ +// set_intersection +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_intersection( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_RandomAccessIterator3 __brick_set_intersection( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_OutputIterator __pattern_set_intersection( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_intersection( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator3 __pattern_set_intersection( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // intersection is empty + if (__n1 == 0 || __n2 == 0) + return __result; + + // testing whether the sequences are intersected + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + //{1} < {2}: seq 2 is wholly greater than seq 1, so, the intersection is empty + if (__left_bound_seq_1 == __last1) + return __result; + + // testing whether the sequences are intersected + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + //{2} < {1}: seq 1 is wholly greater than seq 2, so, the intersection is empty + if (__left_bound_seq_2 == __last2) + return __result; + + const auto __m1 = __last1 - __left_bound_seq_1 + __n2; + if (__m1 > __set_algo_cut_off) { + // we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) + return __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __left_bound_seq_1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_intersection_construct(__first1, __last1, __first2, __last2, __result, __comp); + }); + } + + const auto __m2 = __last2 - __left_bound_seq_2 + __n1; + if (__m2 > __set_algo_cut_off) { + // we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __left_bound_seq_2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_intersection_construct(__first2, __last2, __first1, __last1, __result, __comp); + }); + return __result; + } + + // [left_bound_seq_1; last1) and [left_bound_seq_2; last2) - use serial algorithm + return std::set_intersection(__left_bound_seq_1, __last1, __left_bound_seq_2, __last2, __result, __comp); +} + +//------------------------------------------------------------------------ +// set_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_difference( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_RandomAccessIterator3 __brick_set_difference( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_OutputIterator __pattern_set_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_difference( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator3 __pattern_set_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // {} \ {2}: the difference is empty + if (__n1 == 0) + return __result; + + // {1} \ {}: parallel copying just first sequence + if (__n2 == 0) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + // testing whether the sequences are intersected + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + //{1} < {2}: seq 2 is wholly greater than seq 1, so, parallel copying just first sequence + if (__left_bound_seq_1 == __last1) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + // testing whether the sequences are intersected + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + //{2} < {1}: seq 1 is wholly greater than seq 2, so, parallel copying just first sequence + if (__left_bound_seq_2 == __last2) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + if (__n1 + __n2 > __set_algo_cut_off) + return __parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType) { return __n; }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_difference_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); + + // use serial algorithm + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +//------------------------------------------------------------------------ +// set_symmetric_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_set_symmetric_difference( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_RandomAccessIterator3 __brick_set_symmetric_difference( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template +_OutputIterator __pattern_set_symmetric_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_symmetric_difference( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator3 __pattern_set_symmetric_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // use serial algorithm + if (__n1 + __n2 <= __set_algo_cut_off) + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); + + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + return __internal::__parallel_set_union_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_symmetric_difference_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); +} + +//------------------------------------------------------------------------ +// is_heap_until +//------------------------------------------------------------------------ + +template +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::is_heap_until(__first, __last, __comp); +} + +template +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + if (__last - __first < 2) + return __last; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + return __unseq_backend::__simd_first( + __first, _SizeType(0), __last - __first, [&__comp](_RandomAccessIterator __it, _SizeType __i) { + return __comp(__it[(__i - 1) / 2], __it[__i]); + }); +} + +template +_RandomAccessIterator __pattern_is_heap_until( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) noexcept { + return __internal::__brick_is_heap_until(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __is_heap_until_local( + _RandomAccessIterator __first, + _DifferenceType __begin, + _DifferenceType __end, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + _DifferenceType __i = __begin; + for (; __i < __end; ++__i) { + if (__comp(__first[(__i - 1) / 2], __first[__i])) { + break; + } + } + return __first + __i; +} + +template +_RandomAccessIterator __is_heap_until_local( + _RandomAccessIterator __first, + _DifferenceType __begin, + _DifferenceType __end, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_first( + __first, __begin, __end, [&__comp](_RandomAccessIterator __it, _DifferenceType __i) { + return __comp(__it[(__i - 1) / 2], __it[__i]); + }); +} + +template +_RandomAccessIterator __pattern_is_heap_until( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first < 2) + return __last; + + return __internal::__except_handler([&]() { + return __parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __comp](_RandomAccessIterator __i, _RandomAccessIterator __j) { + return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, _IsVector{}); + }, + std::less::difference_type>(), + /*is_first=*/true); + }); +} + +//------------------------------------------------------------------------ +// min_element +//------------------------------------------------------------------------ + +template +_ForwardIterator __brick_min_element( + _ForwardIterator __first, + _ForwardIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::min_element(__first, __last, __comp); +} + +template +_RandomAccessIterator __brick_min_element( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_UDR_PRESENT) + return __unseq_backend::__simd_min_element(__first, __last - __first, __comp); +#else + return std::min_element(__first, __last, __comp); +#endif +} + +template +_ForwardIterator __pattern_min_element( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) noexcept { + return __internal::__brick_min_element(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator __pattern_min_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + if (__first == __last) + return __last; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first + 1, + __last, + __first, + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _RandomAccessIterator __init) + -> _RandomAccessIterator { + const _RandomAccessIterator subresult = __internal::__brick_min_element(__begin, __end, __comp, _IsVector{}); + return __internal::__cmp_iterators_by_values(__init, subresult, __comp); + }, + [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator { + return __internal::__cmp_iterators_by_values(__it1, __it2, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// minmax_element +//------------------------------------------------------------------------ + +template +std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element( + _ForwardIterator __first, + _ForwardIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::minmax_element(__first, __last, __comp); +} + +template +std::pair<_RandomAccessIterator, _RandomAccessIterator> __brick_minmax_element( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_UDR_PRESENT) + return __unseq_backend::__simd_minmax_element(__first, __last - __first, __comp); +#else + return std::minmax_element(__first, __last, __comp); +#endif +} + +template +std::pair<_ForwardIterator, _ForwardIterator> __pattern_minmax_element( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) noexcept { + return __internal::__brick_minmax_element(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template +std::pair<_RandomAccessIterator, _RandomAccessIterator> __pattern_minmax_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + if (__first == __last) + return std::make_pair(__first, __first); + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + typedef std::pair<_RandomAccessIterator, _RandomAccessIterator> _Result; + + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first + 1, + __last, + std::make_pair(__first, __first), + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Result __init) -> _Result { + const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, _IsVector{}); + return std::make_pair( + __internal::__cmp_iterators_by_values(__subresult.first, __init.first, __comp), + __internal::__cmp_iterators_by_values(__init.second, __subresult.second, std::not_fn(__comp))); + }, + [=](_Result __p1, _Result __p2) -> _Result { + return std::make_pair(__internal::__cmp_iterators_by_values(__p1.first, __p2.first, __comp), + __internal::__cmp_iterators_by_values(__p2.second, __p1.second, std::not_fn(__comp))); + }); + }); +} + +//------------------------------------------------------------------------ +// mismatch +//------------------------------------------------------------------------ +template +std::pair<_ForwardIterator1, _ForwardIterator2> __mismatch_serial( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + return std::mismatch(__first1, __last1, __first2, __last2, __pred); +} + +template +std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Predicate __pred, + /* __is_vector = */ std::false_type) noexcept { + return __mismatch_serial(__first1, __last1, __first2, __last2, __pred); +} + +template +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __brick_mismatch( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Predicate __pred, + /* __is_vector = */ std::true_type) noexcept { + auto __n = std::min(__last1 - __first1, __last2 - __first2); + return __unseq_backend::__simd_first(__first1, __n, __first2, std::not_fn(__pred)); +} + +template +std::pair<_ForwardIterator1, _ForwardIterator2> __pattern_mismatch( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Predicate __pred) noexcept { + return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, typename _Tag::__is_vector{}); +} + +template +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __pattern_mismatch( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Predicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + auto __n = std::min(__last1 - __first1, __last2 - __first2); + auto __result = __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_mismatch( + __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), __pred, _IsVector{}) + .first; + }, + std::less::difference_type>(), + /*is_first=*/true); + return std::make_pair(__result, __first2 + (__result - __first1)); + }); +} + +//------------------------------------------------------------------------ +// lexicographical_compare +//------------------------------------------------------------------------ + +template +bool __brick_lexicographical_compare( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::lexicographical_compare(__first1, __last1, __first2, __last2, __comp); +} + +template +bool __brick_lexicographical_compare( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + if (__first2 == __last2) { // if second sequence is empty + return false; + } else if (__first1 == __last1) { // if first sequence is empty + return true; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference ref_type1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference ref_type2; + --__last1; + --__last2; + auto __n = std::min(__last1 - __first1, __last2 - __first2); + std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __result = __unseq_backend::__simd_first( + __first1, __n, __first2, [__comp](const ref_type1 __x, const ref_type2 __y) mutable { + return __comp(__x, __y) || __comp(__y, __x); + }); + + if (__result.first == __last1 && __result.second != __last2) { // if first sequence shorter than second + return !__comp(*__result.second, *__result.first); + } else { // if second sequence shorter than first or both have the same number of elements + return __comp(*__result.first, *__result.second); + } + } +} + +template +bool __pattern_lexicographical_compare( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) noexcept { + return __internal::__brick_lexicographical_compare( + __first1, __last1, __first2, __last2, __comp, typename _Tag::__is_vector{}); +} + +template +bool __pattern_lexicographical_compare( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first2 == __last2) { // if second sequence is empty + return false; + } else if (__first1 == __last1) { // if first sequence is empty + return true; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _RefType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _RefType2; + --__last1; + --__last2; + auto __n = std::min(__last1 - __first1, __last2 - __first2); + auto __result = __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, &__comp](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_mismatch( + __i, + __j, + __first2 + (__i - __first1), + __first2 + (__j - __first1), + [&__comp](const _RefType1 __x, const _RefType2 __y) { + return !__comp(__x, __y) && !__comp(__y, __x); + }, + _IsVector{}) + .first; + }, + std::less::difference_type>(), + /*is_first=*/true); + + if (__result == __last1 && __first2 + (__result - __first1) != __last2) { // if first sequence shorter than second + return !__comp(*(__first2 + (__result - __first1)), *__result); + } else { // if second sequence shorter than first or both have the same number of elements + return __comp(*__result, *(__first2 + (__result - __first1))); + } + } +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_ALGORITHM_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/execution_defs.h b/lib/libcxx/include/__pstl/internal/execution_defs.h new file mode 100644 index 0000000000..5992f0e4a3 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/execution_defs.h @@ -0,0 +1,76 @@ +// -*- 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 _PSTL_EXECUTION_POLICY_DEFS_H +#define _PSTL_EXECUTION_POLICY_DEFS_H + +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace execution { +inline namespace v1 { + +// 2.4, Sequential execution policy +class sequenced_policy {}; + +// 2.5, Parallel execution policy +class parallel_policy {}; + +// 2.6, Parallel+Vector execution policy +class parallel_unsequenced_policy {}; + +class unsequenced_policy {}; + +// 2.8, Execution policy objects +constexpr sequenced_policy seq{}; +constexpr parallel_policy par{}; +constexpr parallel_unsequenced_policy par_unseq{}; +constexpr unsequenced_policy unseq{}; + +// 2.3, Execution policy type trait +template +struct is_execution_policy : std::false_type {}; + +template <> +struct is_execution_policy<__pstl::execution::sequenced_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::parallel_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::parallel_unsequenced_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::unsequenced_policy> : std::true_type {}; + +template +constexpr bool is_execution_policy_v = __pstl::execution::is_execution_policy<_Tp>::value; +} // namespace v1 +} // namespace execution + +namespace __internal { +template +using __enable_if_execution_policy = + typename std::enable_if<__pstl::execution::is_execution_policy::type>::value, + _Tp>::type; + +template +struct __serial_tag; +template +struct __parallel_tag; + +} // namespace __internal + +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_EXECUTION_POLICY_DEFS_H */ diff --git a/lib/libcxx/include/__pstl/internal/execution_impl.h b/lib/libcxx/include/__pstl/internal/execution_impl.h new file mode 100644 index 0000000000..c3a7405d39 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/execution_impl.h @@ -0,0 +1,97 @@ +// -*- 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 _PSTL_EXECUTION_IMPL_H +#define _PSTL_EXECUTION_IMPL_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_base_of.h> + +#include <__pstl/internal/execution_defs.h> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace __internal { + +template +using __are_iterators_of = std::conjunction< + std::is_base_of<_IteratorTag, typename std::iterator_traits>::iterator_category>...>; + +template +using __are_random_access_iterators = __are_iterators_of; + +struct __serial_backend_tag {}; +struct __tbb_backend_tag {}; +struct __openmp_backend_tag {}; + +# if defined(_PSTL_PAR_BACKEND_TBB) +using __par_backend_tag = __tbb_backend_tag; +# elif defined(_PSTL_PAR_BACKEND_OPENMP) +using __par_backend_tag = __openmp_backend_tag; +# elif defined(_PSTL_PAR_BACKEND_SERIAL) +using __par_backend_tag = __serial_backend_tag; +# else +# error "A parallel backend must be specified"; +# endif + +template +struct __serial_tag { + using __is_vector = _IsVector; +}; + +template +struct __parallel_tag { + using __is_vector = _IsVector; + // backend tag can be change depending on + // TBB availability in the environment + using __backend_tag = __par_backend_tag; +}; + +template +using __tag_type = + typename std::conditional<__internal::__are_random_access_iterators<_IteratorTypes...>::value, + __parallel_tag<_IsVector>, + __serial_tag<_IsVector>>::type; + +template +_LIBCPP_HIDE_FROM_ABI __serial_tag +__select_backend(__pstl::execution::sequenced_policy, _IteratorTypes&&...) { + return {}; +} + +template +_LIBCPP_HIDE_FROM_ABI __serial_tag<__internal::__are_random_access_iterators<_IteratorTypes...>> +__select_backend(__pstl::execution::unsequenced_policy, _IteratorTypes&&...) { + return {}; +} + +template +_LIBCPP_HIDE_FROM_ABI __tag_type +__select_backend(__pstl::execution::parallel_policy, _IteratorTypes&&...) { + return {}; +} + +template +_LIBCPP_HIDE_FROM_ABI __tag_type<__internal::__are_random_access_iterators<_IteratorTypes...>, _IteratorTypes...> +__select_backend(__pstl::execution::parallel_unsequenced_policy, _IteratorTypes&&...) { + return {}; +} + +} // namespace __internal +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_EXECUTION_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_algorithm_defs.h b/lib/libcxx/include/__pstl/internal/glue_algorithm_defs.h new file mode 100644 index 0000000000..00458d5ffb --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_algorithm_defs.h @@ -0,0 +1,655 @@ +// -*- 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 _PSTL_GLUE_ALGORITHM_DEFS_H +#define _PSTL_GLUE_ALGORITHM_DEFS_H + +#include <__config> +#include +#include + +#include "execution_defs.h" + +namespace std { + +// [alg.find.end] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +// [alg.find_first_of] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> find_first_of( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_first_of(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +// [alg.adjacent_find] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred); + +// [alg.count] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred); + +// [alg.search] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +search_n(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n( + _ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value); + +// [alg.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +copy_if(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 result, + _Predicate __pred); + +// [alg.swap] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> swap_ranges( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +// [alg.replace] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +replace_if(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + const _Tp& __new_value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +replace(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + const _Tp& __old_value, + const _Tp& __new_value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> replace_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _UnaryPredicate __pred, + const _Tp& __new_value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> replace_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __old_value, + const _Tp& __new_value); + +// [alg.generate] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size count, _Generator __g); + +// [alg.remove] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> remove_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +remove_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +// [alg.unique] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result); + +// [alg.reverse] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +reverse_copy(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _ForwardIterator __d_first); + +// [alg.rotate] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +rotate_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __middle, + _ForwardIterator1 __last, + _ForwardIterator2 __result); + +// [alg.partitions] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _BidirectionalIterator> stable_partition( + _ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +partition_copy(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardIterator1 __out_true, + _ForwardIterator2 __out_false, + _UnaryPredicate __pred); + +// [alg.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [stable.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [mismatch] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __pred); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +// [alg.equal] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +// [alg.move] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first); + +// [partial.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last); + +// [partial.sort.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last); + +// [is.sorted] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +// [alg.nth.element] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last); + +// [alg.merge] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +merge(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __d_first, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +merge(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __d_first); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last); + +// [includes] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +// [set.union] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.intersection] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.symmetric.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator result, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [is.heap] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [alg.min.max] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +// [alg.lex.comparison] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +} // namespace std + +#endif /* _PSTL_GLUE_ALGORITHM_DEFS_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_algorithm_impl.h b/lib/libcxx/include/__pstl/internal/glue_algorithm_impl.h new file mode 100644 index 0000000000..8e8f2539f8 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_algorithm_impl.h @@ -0,0 +1,972 @@ +// -*- 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 _PSTL_GLUE_ALGORITHM_IMPL_H +#define _PSTL_GLUE_ALGORITHM_IMPL_H + +#include <__config> +#include + +#include "algorithm_fwd.h" +#include "execution_defs.h" +#include "numeric_fwd.h" /* count and count_if use __pattern_transform_reduce */ +#include "utils.h" + +#include "execution_impl.h" + +namespace std { + +// [alg.find.end] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_end( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::find_end(std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +// [alg.find_first_of] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> find_first_of( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_first_of( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_first_of(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::find_first_of( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +// [alg.adjacent_find] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + std::equal_to<_ValueType>(), + /*first_semantic*/ false); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, /*first_semantic*/ false); +} + +// [alg.count] + +// Implementation note: count and count_if call the pattern directly instead of calling std::transform_reduce +// so that we do not have to include . + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return __pstl::__internal::__pattern_count( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value](const _ValueType& __x) { + return __value == __x; + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_count( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +// [alg.search] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_search( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::search(std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +search_n(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_search_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __count, __value, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n( + _ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { + return std::search_n( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __count, + __value, + std::equal_to::value_type>()); +} + +// [alg.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +copy_if(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_copy_if( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred); +} + +// [alg.swap] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> swap_ranges( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + [](_ReferenceType1 __x, _ReferenceType2 __y) { + using std::swap; + swap(__x, __y); + }); +} + +// [alg.generate] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_generate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __g); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, _Generator __g) { + if (__count <= 0) + return __first; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_generate_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __count, __g); +} + +// [alg.remove] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> remove_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred) { + return std::copy_if(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, std::not_fn(__pred)); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +remove_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __value) { + return std::copy_if( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__not_equal_value<_Tp>(__value)); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_remove_if( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::remove_if( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__equal_value<_Tp>(__value)); +} + +// [alg.unique] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_unique( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + return std::unique(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::equal_to<>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_unique_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> unique_copy( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result) { + return std::unique_copy(__exec, __first, __last, __result, std::equal_to<>()); +} + +// [alg.reverse] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_reverse(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +reverse_copy(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _ForwardIterator __d_first) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_reverse_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first); +} + +// [alg.rotate] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_rotate( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +rotate_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __middle, + _ForwardIterator1 __last, + _ForwardIterator2 __result) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_rotate_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __result); +} + +// [alg.partitions] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_is_partitioned( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_partition( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _BidirectionalIterator> stable_partition( + _ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_stable_partition( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +partition_copy(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardIterator1 __out_true, + _ForwardIterator2 __out_false, + _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __out_true, __out_false); + + return __pstl::__internal::__pattern_partition_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __out_true, __out_false, __pred); +} + +// [alg.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + return __pstl::__internal::__pattern_sort( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + typename std::is_move_constructible<_InputType>::type()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [stable.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_stable_sort( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::stable_sort(__exec, __first, __last, std::less<_InputType>()); +} + +// [mismatch] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_mismatch( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __pred) { + return std::mismatch( + __exec, __first1, __last1, __first2, std::next(__first2, std::distance(__first1, __last1)), __pred); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::mismatch(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::equal_to<>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + // TODO: to get rid of "distance" + return std::mismatch( + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + std::next(__first2, std::distance(__first1, __last1))); +} + +// [alg.equal] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __p); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + return std::equal(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, std::equal_to<>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __p); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return equal(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::equal_to<>()); +} + +// [alg.move] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __d_first, + [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) { + return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector{}); + }); +} + +// [partial.sort] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_partial_sort( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) { + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::partial_sort(__exec, __first, __middle, __last, std::less<_InputType>()); +} + +// [partial.sort.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_partial_sort_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last) { + return std::partial_sort_copy( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, std::less<>()); +} + +// [is.sorted] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + const _ForwardIterator __res = __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*first_semantic*/ false); + return __res == __last ? __last : std::next(__res); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return is_sorted_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*or_semantic*/ true) == __last; +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::is_sorted(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [alg.merge] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_inplace_merge( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last) { + typedef typename std::iterator_traits<_BidirectionalIterator>::value_type _InputType; + std::inplace_merge(__exec, __first, __middle, __last, std::less<_InputType>()); +} + +// [includes] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_includes( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::includes(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::less<>()); +} + +// [set.union] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_union( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_union( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.intersection] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_intersection( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_intersection( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_difference( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.symmetric.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_symmetric_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_symmetric_difference( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [is.heap] +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_is_heap_until( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + return std::is_heap_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + return std::is_heap_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp) == __last; +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + return std::is_heap(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [alg.min.max] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_min_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::min_element(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + return min_element( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__reorder_pred<_Compare>(__comp)); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::min_element( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred>(std::less<_InputType>())); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_minmax_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return std::minmax_element(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_ValueType>()); +} + +// [alg.nth.element] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_nth_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last) { + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::nth_element(std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, std::less<_InputType>()); +} + +// [alg.lex.comparison] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_lexicographical_compare( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::lexicographical_compare( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::less<>()); +} + +} // namespace std + +#endif /* _PSTL_GLUE_ALGORITHM_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_memory_defs.h b/lib/libcxx/include/__pstl/internal/glue_memory_defs.h new file mode 100644 index 0000000000..4e8581cfdb --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_memory_defs.h @@ -0,0 +1,81 @@ +// -*- 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 _PSTL_GLUE_MEMORY_DEFS_H +#define _PSTL_GLUE_MEMORY_DEFS_H + +#include <__config> + +#include "execution_defs.h" + +namespace std { + +// [uninitialized.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result); + +// [uninitialized.move] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result); + +// [uninitialized.fill] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, const _Tp& __value); + +// [specialized.destroy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +// [uninitialized.construct.default] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +// [uninitialized.construct.value] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +} // namespace std + +#endif /* _PSTL_GLUE_MEMORY_DEFS_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_memory_impl.h b/lib/libcxx/include/__pstl/internal/glue_memory_impl.h new file mode 100644 index 0000000000..b645ba3fca --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_memory_impl.h @@ -0,0 +1,379 @@ +// -*- 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 _PSTL_GLUE_MEMORY_IMPL_H +#define _PSTL_GLUE_MEMORY_IMPL_H + +#include <__config> + +#include "algorithm_fwd.h" +#include "execution_defs.h" +#include "utils.h" + +#include "execution_impl.h" + +namespace std { + +// [uninitialized.copy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> uninitialized_copy( + _ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { ::new (std::addressof(__val2)) _ValueType2(__val1); }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { ::new (std::addressof(__val2)) _ValueType2(__val1); }); + }); +} + +// [uninitialized.move] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> uninitialized_move( + _ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { + ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); + }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { + ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); + }); + }); +} + +// [uninitialized.fill] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + __pstl::__internal::__invoke_if_else( + std::is_arithmetic<_ValueType>(), + [&]() { + __pstl::__internal::__pattern_walk_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [&__value](_ForwardIterator __begin, _ForwardIterator __end) { + __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector{}); + }); + }, + [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(__value); + }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, const _Tp& __value) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::is_arithmetic<_ValueType>(), + [&]() { + return __pstl::__internal::__pattern_walk_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + [&__value](_ForwardIterator __begin, _Size __count) { + return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [&__value](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(__value); + }); + }); +} + +// [specialized.destroy] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + __val.~_ValueType(); + }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__invoke_if_else( + std::is_trivially_destructible<_ValueType>(), + [&]() { return std::next(__first, __n); }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + __val.~_ValueType(); + }); + }); +} + +// [uninitialized.construct.default] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(), [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType; + }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { return std::next(__first, __n); }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType; + }); + }); +} + +// [uninitialized.construct.value] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { + __pstl::__internal::__pattern_walk_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [](_ForwardIterator __begin, _ForwardIterator __end) { + __pstl::__internal::__brick_fill(__begin, __end, _ValueType(), __is_vector{}); + }); + }, + [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(); + }); + }); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { + return __pstl::__internal::__pattern_walk_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + [](_ForwardIterator __begin, _Size __count) { + return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(), __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(); + }); + }); +} + +} // namespace std + +#endif /* _PSTL_GLUE_MEMORY_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_numeric_defs.h b/lib/libcxx/include/__pstl/internal/glue_numeric_defs.h new file mode 100644 index 0000000000..05c71665eb --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_numeric_defs.h @@ -0,0 +1,124 @@ +// -*- 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 _PSTL_GLUE_NUMERIC_DEFS_H +#define _PSTL_GLUE_NUMERIC_DEFS_H + +#include <__config> +#include + +#include "execution_defs.h" + +namespace std { +// [exclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op); + +// [inclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _Tp __init); + +// [transform.exclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op); + +// [transform.inclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op); + +// [adjacent.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __d_first, + _BinaryOperation op); + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first); + +} // namespace std + +#endif /* _PSTL_GLUE_NUMERIC_DEFS_H */ diff --git a/lib/libcxx/include/__pstl/internal/glue_numeric_impl.h b/lib/libcxx/include/__pstl/internal/glue_numeric_impl.h new file mode 100644 index 0000000000..4e6516a06c --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/glue_numeric_impl.h @@ -0,0 +1,223 @@ +// -*- 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 _PSTL_GLUE_NUMERIC_IMPL_H +#define _PSTL_GLUE_NUMERIC_IMPL_H + +#include <__config> +#include + +#include "execution_impl.h" +#include "numeric_fwd.h" +#include "utils.h" + +namespace std { + +// [exclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using namespace __pstl; + return __internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__no_op(), + __init, + std::plus<_Tp>(), + /*inclusive=*/std::false_type()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using namespace __pstl; + return __internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__no_op(), + __init, + __binary_op, + /*inclusive=*/std::false_type()); +} + +// [inclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result) { + typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType; + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + std::plus<_InputType>(), + __pstl::__internal::__no_op()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op) { + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op, __pstl::__internal::__no_op()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _Tp __init) { + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __binary_op, + __pstl::__internal::__no_op(), + __init); +} + +// [transform.exclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + /*inclusive=*/std::false_type()); +} + +// [transform.inclusive.scan] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + /*inclusive=*/std::true_type()); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) { + if (__first != __last) { + auto __tmp = __unary_op(*__first); + *__result = __tmp; + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), ++__first, __last, ++__result, __binary_op, __unary_op, __tmp); + } else { + return __result; + } +} + +// [adjacent.difference] + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __d_first, + _BinaryOperation __op) { + if (__first == __last) + return __d_first; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_adjacent_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __op); +} + +template +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first) { + typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType; + return adjacent_difference( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, std::minus<_ValueType>()); +} + +} // namespace std + +#endif /* _PSTL_GLUE_NUMERIC_IMPL_H_ */ diff --git a/lib/libcxx/include/__pstl/internal/memory_impl.h b/lib/libcxx/include/__pstl/internal/memory_impl.h new file mode 100644 index 0000000000..5315ccd9a3 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/memory_impl.h @@ -0,0 +1,106 @@ +// -*- 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 _PSTL_MEMORY_IMPL_H +#define _PSTL_MEMORY_IMPL_H + +#include <__config> +#include + +#include "unseq_backend_simd.h" + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// uninitialized_move +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_uninitialized_move( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + for (; __first != __last; ++__first, ++__result) { + ::new (std::addressof(*__result)) _ValueType(std::move(*__first)); + } + return __result; +} + +template +_OutputIterator __brick_uninitialized_move( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + /*vector=*/std::true_type) noexcept { + using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; + using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; + + return __unseq_backend::__simd_walk_2( + __first, __last - __first, __result, [](_ReferenceType1 __x, _ReferenceType2 __y) { + ::new (std::addressof(__y)) __ValueType(std::move(__x)); + }); +} + +template +void __brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_Iterator>::value_type; + + for (; __first != __last; ++__first) + __first->~_ValueType(); +} + +template +void __brick_destroy(_RandomAccessIterator __first, _RandomAccessIterator __last, /*vector*/ std::true_type) noexcept { + using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type; + using _ReferenceType = typename std::iterator_traits<_RandomAccessIterator>::reference; + + __unseq_backend::__simd_walk_1(__first, __last - __first, [](_ReferenceType __x) { __x.~_ValueType(); }); +} + +//------------------------------------------------------------------------ +// uninitialized copy +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_uninitialized_copy( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + for (; __first != __last; ++__first, ++__result) { + ::new (std::addressof(*__result)) _ValueType(*__first); + } + return __result; +} + +template +_OutputIterator __brick_uninitialized_copy( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + /*vector=*/std::true_type) noexcept { + using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; + using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; + + return __unseq_backend::__simd_walk_2( + __first, __last - __first, __result, [](_ReferenceType1 __x, _ReferenceType2 __y) { + ::new (std::addressof(__y)) __ValueType(__x); + }); +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_MEMORY_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/numeric_fwd.h b/lib/libcxx/include/__pstl/internal/numeric_fwd.h new file mode 100644 index 0000000000..09f9b11d62 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/numeric_fwd.h @@ -0,0 +1,143 @@ +// -*- 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 _PSTL_NUMERIC_FWD_H +#define _PSTL_NUMERIC_FWD_H + +#include <__config> +#include +#include + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// transform_exclusive_scan +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +template +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + /*Inclusive*/ std::false_type) noexcept; + +template +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + /*Inclusive*/ std::true_type) noexcept; + +template +_OutputIterator __pattern_transform_scan( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive) noexcept; + +template +typename std::enable_if::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive); + +template +typename std::enable_if::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive); + +//------------------------------------------------------------------------ +// adjacent_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_adjacent_difference( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _BinaryOperation, + /*is_vector*/ std::false_type) noexcept; + +template +_OutputIterator __brick_adjacent_difference( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryOperation, + /*is_vector*/ std::true_type) noexcept; + +template +_OutputIterator __pattern_adjacent_difference( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation) noexcept; + +template +_OutputIterator __pattern_adjacent_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryOperation); + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_NUMERIC_FWD_H */ diff --git a/lib/libcxx/include/__pstl/internal/numeric_impl.h b/lib/libcxx/include/__pstl/internal/numeric_impl.h new file mode 100644 index 0000000000..484f26ade2 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/numeric_impl.h @@ -0,0 +1,364 @@ +// -*- 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 _PSTL_NUMERIC_IMPL_H +#define _PSTL_NUMERIC_IMPL_H + +#include <__assert> +#include <__config> +#include +#include +#include + +#include "parallel_backend.h" +#include "execution_impl.h" +#include "unseq_backend_simd.h" +#include "algorithm_fwd.h" + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// transform_exclusive_scan +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +// Exclusive form +template +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + /*Inclusive*/ std::false_type, + /*is_vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__result) { + *__result = __init; + __init = __binary_op(__init, __unary_op(*__first)); + } + return std::make_pair(__result, __init); +} + +// Inclusive form +template +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + /*Inclusive*/ std::true_type, + /*is_vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__result) { + __init = __binary_op(__init, __unary_op(*__first)); + *__result = __init; + } + return std::make_pair(__result, __init); +} + +// type is arithmetic and binary operation is a user defined operation. +template +using is_arithmetic_udop = + std::integral_constant::value && !std::is_same<_BinaryOperation, std::plus<_Tp>>::value>; + +// [restriction] - T shall be DefaultConstructible. +// [violation] - default ctor of T shall set the identity value for binary_op. +template +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive, + /*is_vector=*/std::true_type) noexcept { +#if defined(_PSTL_UDS_PRESENT) + return __unseq_backend::__simd_scan( + __first, __last - __first, __result, __unary_op, __init, __binary_op, _Inclusive()); +#else + // We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() + // value + return __internal::__brick_transform_scan( + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + _Inclusive(), + /*is_vector=*/std::false_type()); +#endif +} + +template +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive, + /*is_vector=*/std::true_type) noexcept { + return __internal::__brick_transform_scan( + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + _Inclusive(), + /*is_vector=*/std::false_type()); +} + +template +_OutputIterator __pattern_transform_scan( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) noexcept { + return __internal::__brick_transform_scan( + __first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(), typename _Tag::__is_vector{}) + .first; +} + +template +typename std::enable_if::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_transform_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __last - __first, + [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, + __init, + __binary_op, + [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) { + // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a + // commutative operation for the guarantee of correct scan. + return __internal::__brick_transform_reduce( + __first + __i, + __first + __j, + __init, + __binary_op, + __unary_op, + /*__is_vector*/ std::false_type()); + }, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init) { + return __internal::__brick_transform_scan( + __first + __i, + __first + __j, + __result + __i, + __unary_op, + __init, + __binary_op, + _Inclusive(), + _IsVector{}) + .second; + }); + return __result + (__last - __first); + }); +} + +template +typename std::enable_if::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + _DifferenceType __n = __last - __first; + + if (__n <= 0) { + return __result; + } + return __internal::__except_handler([&]() { + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + __init, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len) { + return __internal::__brick_transform_scan( + __first + __i, + __first + (__i + __len), + __result + __i, + __unary_op, + _Tp{}, + __binary_op, + _Inclusive(), + _IsVector{}) + .second; + }, + __binary_op, + [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) { + return *(std::transform(__result + __i, + __result + __i + __len, + __result + __i, + [&__initial, &__binary_op](const _Tp& __x) { + return __binary_op(__initial, __x); + }) - + 1); + }, + [](_Tp) {}); + return __result + (__last - __first); + }); +} + +//------------------------------------------------------------------------ +// adjacent_difference +//------------------------------------------------------------------------ + +template +_OutputIterator __brick_adjacent_difference( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __d_first, + _BinaryOperation __op, + /*is_vector*/ std::false_type) noexcept { + return std::adjacent_difference(__first, __last, __d_first, __op); +} + +template +_RandomAccessIterator2 __brick_adjacent_difference( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + BinaryOperation __op, + /*is_vector=*/std::true_type) noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "Range cannot be empty"); + + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + auto __n = __last - __first; + *__d_first = *__first; + return __unseq_backend::__simd_walk_3( + __first + 1, + __n - 1, + __first, + __d_first + 1, + [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__x, __y); }); +} + +template +_OutputIterator __pattern_adjacent_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __d_first, + _BinaryOperation __op) noexcept { + return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, typename _Tag::__is_vector{}); +} + +template +_RandomAccessIterator2 __pattern_adjacent_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + _BinaryOperation __op) { + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range cannot be empty"); + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + *__d_first = *__first; + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last - 1, + [&__op, __d_first, __first](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) { + _RandomAccessIterator2 __d_b = __d_first + (__b - __first); + __internal::__brick_walk3( + __b, + __e, + __b + 1, + __d_b + 1, + [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); }, + _IsVector{}); + }); + return __d_first + (__last - __first); +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_NUMERIC_IMPL_H */ diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_for.h b/lib/libcxx/include/__pstl/internal/omp/parallel_for.h new file mode 100644 index 0000000000..0f841e5311 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_for.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_FOR_H +#define _PSTL_INTERNAL_OMP_PARALLEL_FOR_H + +#include + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +void +__parallel_for_body(_Index __first, _Index __last, _Fp __f) +{ + // initial partition of the iteration space into chunks + auto __policy = __omp_backend::__chunk_partitioner(__first, __last); + + // To avoid over-subscription we use taskloop for the nested parallelism + _PSTL_PRAGMA(omp taskloop untied mergeable) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first, __chunk, __f); + } +} + +//------------------------------------------------------------------------ +// Notation: +// Evaluation of brick f[i,j) for each subrange [i,j) of [first, last) +//------------------------------------------------------------------------ + +template +void +__parallel_for(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +{ + if (omp_in_parallel()) + { + // we don't create a nested parallel region in an existing parallel + // region: just create tasks + __pstl::__omp_backend::__parallel_for_body(__first, __last, __f); + } + else + { + // in any case (nested or non-nested) one parallel region is created and + // only one thread creates a set of tasks + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) { __pstl::__omp_backend::__parallel_for_body(__first, __last, __f); } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_FOR_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_for_each.h b/lib/libcxx/include/__pstl/internal/omp/parallel_for_each.h new file mode 100644 index 0000000000..b9bfb05930 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_for_each.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H +#define _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +void +__parallel_for_each_body(_ForwardIterator __first, _ForwardIterator __last, _Fp __f) +{ + using DifferenceType = typename std::iterator_traits<_ForwardIterator>::difference_type; + // TODO: Think of an approach to remove the std::distance call + auto __size = std::distance(__first, __last); + + _PSTL_PRAGMA(omp taskloop untied mergeable) + for (DifferenceType __index = 0; __index < __size; ++__index) + { + // TODO: Think of an approach to remove the increment here each time. + auto __iter = std::next(__first, __index); + __f(*__iter); + } +} + +template +void +__parallel_for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Fp __f) +{ + if (omp_in_parallel()) + { + // we don't create a nested parallel region in an existing parallel + // region: just create tasks + __pstl::__omp_backend::__parallel_for_each_body(__first, __last, __f); + } + else + { + // in any case (nested or non-nested) one parallel region is created and + // only one thread creates a set of tasks + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) { __pstl::__omp_backend::__parallel_for_each_body(__first, __last, __f); } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_invoke.h b/lib/libcxx/include/__pstl/internal/omp/parallel_invoke.h new file mode 100644 index 0000000000..045ccbe9a1 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_invoke.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +void +__parallel_invoke_body(_F1&& __f1, _F2&& __f2) +{ + _PSTL_PRAGMA(omp taskgroup) + { + _PSTL_PRAGMA(omp task untied mergeable) { std::forward<_F1>(__f1)(); } + _PSTL_PRAGMA(omp task untied mergeable) { std::forward<_F2>(__f2)(); } + } +} + +template +void +__parallel_invoke(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_invoke_body(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + __pstl::__omp_backend::__parallel_invoke_body(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_merge.h b/lib/libcxx/include/__pstl/internal/omp/parallel_merge.h new file mode 100644 index 0000000000..e6f82c5e18 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_merge.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +void +__parallel_merge_body(std::size_t __size_x, std::size_t __size_y, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) +{ + + if (__size_x + __size_y <= __omp_backend::__default_chunk_size) + { + __leaf_merge(__xs, __xe, __ys, __ye, __zs, __comp); + return; + } + + _RandomAccessIterator1 __xm; + _RandomAccessIterator2 __ym; + + if (__size_x < __size_y) + { + __ym = __ys + (__size_y / 2); + __xm = std::upper_bound(__xs, __xe, *__ym, __comp); + } + else + { + __xm = __xs + (__size_x / 2); + __ym = std::lower_bound(__ys, __ye, *__xm, __comp); + } + + auto __zm = __zs + (__xm - __xs) + (__ym - __ys); + + _PSTL_PRAGMA(omp task untied mergeable default(none) + firstprivate(__xs, __xm, __ys, __ym, __zs, __comp, __leaf_merge)) + __pstl::__omp_backend::__parallel_merge_body(__xm - __xs, __ym - __ys, __xs, __xm, __ys, __ym, __zs, __comp, + __leaf_merge); + + _PSTL_PRAGMA(omp task untied mergeable default(none) + firstprivate(__xm, __xe, __ym, __ye, __zm, __comp, __leaf_merge)) + __pstl::__omp_backend::__parallel_merge_body(__xe - __xm, __ye - __ym, __xm, __xe, __ym, __ye, __zm, __comp, + __leaf_merge); + + _PSTL_PRAGMA(omp taskwait) +} + +template +void +__parallel_merge(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&& /*__exec*/, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) + +{ + std::size_t __size_x = __xe - __xs; + std::size_t __size_y = __ye - __ys; + + /* + * Run the merge in parallel by chunking it up. Use the smaller range (if any) as the iteration range, and the + * larger range as the search range. + */ + + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_merge_body(__size_x, __size_y, __xs, __xe, __ys, __ye, __zs, __comp, + __leaf_merge); + } + else + { + _PSTL_PRAGMA(omp parallel) + { + _PSTL_PRAGMA(omp single nowait) + __pstl::__omp_backend::__parallel_merge_body(__size_x, __size_y, __xs, __xe, __ys, __ye, __zs, __comp, + __leaf_merge); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_reduce.h b/lib/libcxx/include/__pstl/internal/omp/parallel_reduce.h new file mode 100644 index 0000000000..841d48fc30 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_reduce.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +_Value +__parallel_reduce_body(_RandomAccessIterator __first, _RandomAccessIterator __last, _Value __identity, + _RealBody __real_body, _Reduction __reduce) +{ + if (__should_run_serial(__first, __last)) + { + return __real_body(__first, __last, __identity); + } + + auto __middle = __first + ((__last - __first) / 2); + _Value __v1(__identity), __v2(__identity); + __parallel_invoke_body( + [&]() { __v1 = __parallel_reduce_body(__first, __middle, __identity, __real_body, __reduce); }, + [&]() { __v2 = __parallel_reduce_body(__middle, __last, __identity, __real_body, __reduce); }); + + return __reduce(__v1, __v2); +} + +//------------------------------------------------------------------------ +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// c(x,y) combines values x and y that were the result of r +//------------------------------------------------------------------------ + +template +_Value +__parallel_reduce(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Value __identity, _RealBody __real_body, _Reduction __reduction) +{ + // We don't create a nested parallel region in an existing parallel region: + // just create tasks. + if (omp_in_parallel()) + { + return __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); + } + + // In any case (nested or non-nested) one parallel region is created and only + // one thread creates a set of tasks. + _Value __res = __identity; + + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __res = __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); + } + + return __res; +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_scan.h b/lib/libcxx/include/__pstl/internal/omp/parallel_scan.h new file mode 100644 index 0000000000..f3eb967ca4 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_scan.h @@ -0,0 +1,136 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H +#define _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H + +#include "parallel_invoke.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +_Index +__split(_Index __m) +{ + _Index __k = 1; + while (2 * __k < __m) + __k *= 2; + return __k; +} + +template +void +__upsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Rp __reduce, _Cp __combine) +{ + if (__m == 1) + __r[0] = __reduce(__i * __tilesize, __lastsize); + else + { + _Index __k = __split(__m); + __omp_backend::__parallel_invoke_body( + [=] { __omp_backend::__upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); }, + [=] { + __omp_backend::__upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); + }); + if (__m == 2 * __k) + __r[__m - 1] = __combine(__r[__k - 1], __r[__m - 1]); + } +} + +template +void +__downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Tp __initial, _Cp __combine, + _Sp __scan) +{ + if (__m == 1) + __scan(__i * __tilesize, __lastsize, __initial); + else + { + const _Index __k = __split(__m); + __omp_backend::__parallel_invoke_body( + [=] { __omp_backend::__downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); }, + // Assumes that __combine never throws. + // TODO: Consider adding a requirement for user functors to be constant. + [=, &__combine] + { + __omp_backend::__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, + __combine(__initial, __r[__k - 1]), __combine, __scan); + }); + } +} + +template +void +__parallel_strict_scan_body(_Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + _Index __p = omp_get_num_threads(); + const _Index __slack = 4; + _Index __tilesize = (__n - 1) / (__slack * __p) + 1; + _Index __m = (__n - 1) / __tilesize; + __buffer<_Tp> __buf(__m + 1); + _Tp* __r = __buf.get(); + + __omp_backend::__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, __combine); + + std::size_t __k = __m + 1; + _Tp __t = __r[__k - 1]; + while ((__k &= __k - 1)) + { + __t = __combine(__r[__k - 1], __t); + } + + __apex(__combine(__initial, __t)); + __omp_backend::__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, + __combine, __scan); +} + +template +void +__parallel_strict_scan(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + if (__n <= __default_chunk_size) + { + _Tp __sum = __initial; + if (__n) + { + __sum = __combine(__sum, __reduce(_Index(0), __n)); + } + __apex(__sum); + if (__n) + { + __scan(_Index(0), __n, __initial); + } + return; + } + + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_strict_scan_body<_ExecutionPolicy>(__n, __initial, __reduce, __combine, + __scan, __apex); + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __pstl::__omp_backend::__parallel_strict_scan_body<_ExecutionPolicy>(__n, __initial, __reduce, __combine, + __scan, __apex); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h b/lib/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h new file mode 100644 index 0000000000..06cd55bb48 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H +#define _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +void +__parallel_stable_partial_sort(__pstl::__internal::__openmp_backend_tag, _RandomAccessIterator __xs, + _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, + std::size_t /* __nsort */) +{ + // TODO: "Parallel partial sort needs to be implemented."); + __leaf_sort(__xs, __xe, __comp); +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h b/lib/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h new file mode 100644 index 0000000000..e4d0676627 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h @@ -0,0 +1,160 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H +#define _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H + +#include "util.h" +#include "parallel_merge.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +namespace __sort_details +{ +struct __move_value +{ + template + void + operator()(_Iterator __x, _OutputIterator __z) const + { + *__z = std::move(*__x); + } +}; + +template +_OutputIterator +__parallel_move_range(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _OutputIterator __d_first) +{ + std::size_t __size = __last1 - __first1; + + // Perform serial moving of small chunks + + if (__size <= __default_chunk_size) + { + return std::move(__first1, __last1, __d_first); + } + + // Perform parallel moving of larger chunks + auto __policy = __pstl::__omp_backend::__chunk_partitioner(__first1, __last1); + + _PSTL_PRAGMA(omp taskloop) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first1, __chunk, + [&](auto __chunk_first, auto __chunk_last) + { + auto __chunk_offset = __chunk_first - __first1; + auto __output_it = __d_first + __chunk_offset; + std::move(__chunk_first, __chunk_last, __output_it); + }); + } + + return __d_first + __size; +} + +struct __move_range +{ + template + _OutputIterator + operator()(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _OutputIterator __d_first) const + { + return __pstl::__omp_backend::__sort_details::__parallel_move_range(__first1, __last1, __d_first); + } +}; +} // namespace __sort_details + +template +void +__parallel_stable_sort_body(_RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp, + _LeafSort __leaf_sort) +{ + using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type; + using _VecType = typename std::vector<_ValueType>; + using _OutputIterator = typename _VecType::iterator; + using _MoveValue = typename __omp_backend::__sort_details::__move_value; + using _MoveRange = __omp_backend::__sort_details::__move_range; + + if (__should_run_serial(__xs, __xe)) + { + __leaf_sort(__xs, __xe, __comp); + } + else + { + std::size_t __size = __xe - __xs; + auto __mid = __xs + (__size / 2); + __pstl::__omp_backend::__parallel_invoke_body( + [&]() { __parallel_stable_sort_body(__xs, __mid, __comp, __leaf_sort); }, + [&]() { __parallel_stable_sort_body(__mid, __xe, __comp, __leaf_sort); }); + + // Perform a parallel merge of the sorted ranges into __output_data. + _VecType __output_data(__size); + _MoveValue __move_value; + _MoveRange __move_range; + __utils::__serial_move_merge __merge(__size); + __pstl::__omp_backend::__parallel_merge_body( + __mid - __xs, __xe - __mid, __xs, __mid, __mid, __xe, __output_data.begin(), __comp, + [&__merge, &__move_value, &__move_range](_RandomAccessIterator __as, _RandomAccessIterator __ae, + _RandomAccessIterator __bs, _RandomAccessIterator __be, + _OutputIterator __cs, _Compare __comp) + { __merge(__as, __ae, __bs, __be, __cs, __comp, __move_value, __move_value, __move_range, __move_range); }); + + // Move the values from __output_data back in the original source range. + __pstl::__omp_backend::__sort_details::__parallel_move_range(__output_data.begin(), __output_data.end(), __xs); + } +} + +template +void +__parallel_stable_sort(__pstl::__internal::__openmp_backend_tag __tag, _ExecutionPolicy&& /*__exec*/, + _RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, + std::size_t __nsort = 0) +{ + auto __count = static_cast(__xe - __xs); + if (__count <= __default_chunk_size || __nsort < __count) + { + __leaf_sort(__xs, __xe, __comp); + return; + } + + // TODO: the partial sort implementation should + // be shared with the other backends. + + if (omp_in_parallel()) + { + if (__count <= __nsort) + { + __pstl::__omp_backend::__parallel_stable_sort_body(__xs, __xe, __comp, __leaf_sort); + } + else + { + __pstl::__omp_backend::__parallel_stable_partial_sort(__tag, __xs, __xe, __comp, __leaf_sort, __nsort); + } + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + if (__count <= __nsort) + { + __pstl::__omp_backend::__parallel_stable_sort_body(__xs, __xe, __comp, __leaf_sort); + } + else + { + __pstl::__omp_backend::__parallel_stable_partial_sort(__tag, __xs, __xe, __comp, __leaf_sort, __nsort); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h b/lib/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h new file mode 100644 index 0000000000..1d4cc0a597 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h @@ -0,0 +1,113 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +//------------------------------------------------------------------------ +// parallel_transform_reduce +// +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// u(i) returns f(i,i+1,identity) for a hypothetical left identity element +// of r c(x,y) combines values x and y that were the result of r or u +//------------------------------------------------------------------------ + +template +auto +__transform_reduce_body(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryOp __unary_op, _Value __init, + _Combiner __combiner, _Reduction __reduction) +{ + const std::size_t __num_threads = omp_get_num_threads(); + const std::size_t __size = __last - __first; + + // Initial partition of the iteration space into chunks. If the range is too small, + // this will result in a nonsense policy, so we check on the size as well below. + auto __policy = __omp_backend::__chunk_partitioner(__first + __num_threads, __last); + + if (__size <= __num_threads || __policy.__n_chunks < 2) + { + return __reduction(__first, __last, __init); + } + + // Here, we cannot use OpenMP UDR because we must store the init value in + // the combiner and it will be used several times. Although there should be + // the only one; we manually generate the identity elements for each thread. + std::vector<_Value> __accums; + __accums.reserve(__num_threads); + + // initialize accumulators for all threads + for (std::size_t __i = 0; __i < __num_threads; ++__i) + { + __accums.emplace_back(__unary_op(__first + __i)); + } + + // main loop + _PSTL_PRAGMA(omp taskloop shared(__accums)) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first + __num_threads, __chunk, + [&](auto __chunk_first, auto __chunk_last) + { + auto __thread_num = omp_get_thread_num(); + __accums[__thread_num] = + __reduction(__chunk_first, __chunk_last, __accums[__thread_num]); + }); + } + + // combine by accumulators + for (std::size_t __i = 0; __i < __num_threads; ++__i) + { + __init = __combiner(__init, __accums[__i]); + } + + return __init; +} + +template +_Value +__parallel_transform_reduce(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryOp __unary_op, _Value __init, _Combiner __combiner, + _Reduction __reduction) +{ + _Value __result = __init; + if (omp_in_parallel()) + { + // We don't create a nested parallel region in an existing parallel + // region: just create tasks + __result = __pstl::__omp_backend::__transform_reduce_body(__first, __last, __unary_op, __init, __combiner, + __reduction); + } + else + { + // Create a parallel region, and a single thread will create tasks + // for the region. + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __result = __pstl::__omp_backend::__transform_reduce_body(__first, __last, __unary_op, __init, __combiner, + __reduction); + } + } + + return __result; +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H diff --git a/lib/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h b/lib/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h new file mode 100644 index 0000000000..f83628994b --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H +#define _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template +_Tp +__parallel_transform_scan(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __n, _Up /* __u */, + _Tp __init, _Cp /* __combine */, _Rp /* __brick_reduce */, _Sp __scan) +{ + // TODO: parallelize this function. + return __scan(_Index(0), __n, __init); +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H diff --git a/lib/libcxx/include/__pstl/internal/omp/util.h b/lib/libcxx/include/__pstl/internal/omp/util.h new file mode 100644 index 0000000000..3c1a92e03c --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/omp/util.h @@ -0,0 +1,171 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_UTIL_H +#define _PSTL_INTERNAL_OMP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../parallel_backend_utils.h" +#include "../unseq_backend_simd.h" +#include "../utils.h" + +// Portability "#pragma" definition +#ifdef _MSC_VER +# define _PSTL_PRAGMA(x) __pragma(x) +#else +# define _PSTL_PRAGMA(x) _Pragma(# x) +#endif + +namespace __pstl +{ +namespace __omp_backend +{ + +//------------------------------------------------------------------------ +// use to cancel execution +//------------------------------------------------------------------------ +inline void +__cancel_execution() +{ + // TODO: Figure out how to make cancelation work. +} + +//------------------------------------------------------------------------ +// raw buffer +//------------------------------------------------------------------------ + +template +class __buffer +{ + std::allocator<_Tp> __allocator_; + _Tp* __ptr_; + const std::size_t __buf_size_; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + __buffer(std::size_t __n) : __allocator_(), __ptr_(__allocator_.allocate(__n)), __buf_size_(__n) {} + + operator bool() const { return __ptr_ != nullptr; } + + _Tp* + get() const + { + return __ptr_; + } + ~__buffer() { __allocator_.deallocate(__ptr_, __buf_size_); } +}; + +// Preliminary size of each chunk: requires further discussion +inline constexpr std::size_t __default_chunk_size = 2048; + +// Convenience function to determine when we should run serial. +template ::value, bool> = true> +constexpr auto +__should_run_serial(_Iterator __first, _Iterator __last) -> bool +{ + using _difference_type = typename std::iterator_traits<_Iterator>::difference_type; + auto __size = std::distance(__first, __last); + return __size <= static_cast<_difference_type>(__default_chunk_size); +} + +template ::value, bool> = true> +constexpr auto +__should_run_serial(_Index __first, _Index __last) -> bool +{ + using _difference_type = _Index; + auto __size = __last - __first; + return __size <= static_cast<_difference_type>(__default_chunk_size); +} + +struct __chunk_metrics +{ + std::size_t __n_chunks; + std::size_t __chunk_size; + std::size_t __first_chunk_size; +}; + +// The iteration space partitioner according to __requested_chunk_size +template +auto +__chunk_partitioner(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Size __requested_chunk_size = __default_chunk_size) -> __chunk_metrics +{ + /* + * This algorithm improves distribution of elements in chunks by avoiding + * small tail chunks. The leftover elements that do not fit neatly into + * the chunk size are redistributed to early chunks. This improves + * utilization of the processor's prefetch and reduces the number of + * tasks needed by 1. + */ + + const _Size __n = __last - __first; + _Size __n_chunks = 0; + _Size __chunk_size = 0; + _Size __first_chunk_size = 0; + if (__n < __requested_chunk_size) + { + __chunk_size = __n; + __first_chunk_size = __n; + __n_chunks = 1; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + + __n_chunks = (__n / __requested_chunk_size) + 1; + __chunk_size = __n / __n_chunks; + __first_chunk_size = __chunk_size; + const _Size __n_leftover_items = __n - (__n_chunks * __chunk_size); + + if (__n_leftover_items == __chunk_size) + { + __n_chunks += 1; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + else if (__n_leftover_items == 0) + { + __first_chunk_size = __chunk_size; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + + const _Size __n_extra_items_per_chunk = __n_leftover_items / __n_chunks; + const _Size __n_final_leftover_items = __n_leftover_items - (__n_extra_items_per_chunk * __n_chunks); + + __chunk_size += __n_extra_items_per_chunk; + __first_chunk_size = __chunk_size + __n_final_leftover_items; + + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; +} + +template +void +__process_chunk(const __chunk_metrics& __metrics, _Iterator __base, _Index __chunk_index, _Func __f) +{ + auto __this_chunk_size = __chunk_index == 0 ? __metrics.__first_chunk_size : __metrics.__chunk_size; + auto __index = __chunk_index == 0 ? 0 + : (__chunk_index * __metrics.__chunk_size) + + (__metrics.__first_chunk_size - __metrics.__chunk_size); + auto __first = __base + __index; + auto __last = __first + __this_chunk_size; + __f(__first, __last); +} + +} // namespace __omp_backend +} // namespace __pstl + +#endif // _PSTL_INTERNAL_OMP_UTIL_H diff --git a/lib/libcxx/include/__pstl/internal/parallel_backend.h b/lib/libcxx/include/__pstl/internal/parallel_backend.h new file mode 100644 index 0000000000..9c30ee1427 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/parallel_backend.h @@ -0,0 +1,39 @@ +// -*- 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 _PSTL_PARALLEL_BACKEND_H +#define _PSTL_PARALLEL_BACKEND_H + +#include <__config> + +#if defined(_PSTL_PAR_BACKEND_SERIAL) +# include "parallel_backend_serial.h" +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 +namespace __pstl +{ +namespace __par_backend = __serial_backend; +} // namespace __pstl +# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 +#elif defined(_PSTL_PAR_BACKEND_TBB) +# include "parallel_backend_tbb.h" +namespace __pstl +{ +namespace __par_backend = __tbb_backend; +} +#elif defined(_PSTL_PAR_BACKEND_OPENMP) +# include "parallel_backend_omp.h" +namespace __pstl +{ +namespace __par_backend = __omp_backend; +} +#else +# error "No backend set" +#endif + +#endif /* _PSTL_PARALLEL_BACKEND_H */ diff --git a/lib/libcxx/include/__pstl/internal/parallel_backend_omp.h b/lib/libcxx/include/__pstl/internal/parallel_backend_omp.h new file mode 100644 index 0000000000..7398cfe559 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/parallel_backend_omp.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_OMP_H +#define _PSTL_PARALLEL_BACKEND_OMP_H + +//------------------------------------------------------------------------ +// parallel_invoke +//------------------------------------------------------------------------ + +#include "./omp/parallel_invoke.h" + +//------------------------------------------------------------------------ +// parallel_for +//------------------------------------------------------------------------ + +#include "./omp/parallel_for.h" + +//------------------------------------------------------------------------ +// parallel_for_each +//------------------------------------------------------------------------ + +#include "./omp/parallel_for_each.h" + +//------------------------------------------------------------------------ +// parallel_reduce +//------------------------------------------------------------------------ + +#include "./omp/parallel_reduce.h" +#include "./omp/parallel_transform_reduce.h" + +//------------------------------------------------------------------------ +// parallel_scan +//------------------------------------------------------------------------ + +#include "./omp/parallel_scan.h" +#include "./omp/parallel_transform_scan.h" + +//------------------------------------------------------------------------ +// parallel_stable_sort +//------------------------------------------------------------------------ + +#include "./omp/parallel_stable_partial_sort.h" +#include "./omp/parallel_stable_sort.h" + +//------------------------------------------------------------------------ +// parallel_merge +//------------------------------------------------------------------------ +#include "./omp/parallel_merge.h" + +#endif //_PSTL_PARALLEL_BACKEND_OMP_H diff --git a/lib/libcxx/include/__pstl/internal/parallel_backend_serial.h b/lib/libcxx/include/__pstl/internal/parallel_backend_serial.h new file mode 100644 index 0000000000..dd72222f20 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/parallel_backend_serial.h @@ -0,0 +1,106 @@ +// -*- 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 _PSTL_PARALLEL_BACKEND_SERIAL_H +#define _PSTL_PARALLEL_BACKEND_SERIAL_H + +#include <__config> +#include <__memory/allocator.h> +#include <__pstl/internal/execution_impl.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl +{ +namespace __serial_backend +{ + +template +class __buffer +{ + std::allocator<_Tp> __allocator_; + _Tp* __ptr_; + const std::size_t __buf_size_; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + _LIBCPP_HIDE_FROM_ABI + __buffer(std::size_t __n) : __allocator_(), __ptr_(__allocator_.allocate(__n)), __buf_size_(__n) {} + + _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ptr_ != nullptr; } + _LIBCPP_HIDE_FROM_ABI _Tp* + get() const + { + return __ptr_; + } + _LIBCPP_HIDE_FROM_ABI ~__buffer() { __allocator_.deallocate(__ptr_, __buf_size_); } +}; + +template +_LIBCPP_HIDE_FROM_ABI _Value +__parallel_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction&) +{ + if (__first == __last) + { + return __identity; + } + else + { + return __real_body(__first, __last, __identity); + } +} + +template +_LIBCPP_HIDE_FROM_ABI void +__parallel_strict_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + _Tp __sum = __initial; + if (__n) + __sum = __combine(__sum, __reduce(_Index(0), __n)); + __apex(__sum); + if (__n) + __scan(_Index(0), __n, __initial); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _UnaryOp, + _Tp __init, _BinaryOp, _Reduce, _Scan __scan) +{ + return __scan(_Index(0), __n, __init); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__parallel_stable_sort(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort, std::size_t = 0) +{ + __leaf_sort(__first, __last, __comp); +} + +template +_LIBCPP_HIDE_FROM_ABI void +__parallel_invoke(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + std::forward<_F1>(__f1)(); + std::forward<_F2>(__f2)(); +} + +} // namespace __serial_backend +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_PARALLEL_BACKEND_SERIAL_H */ diff --git a/lib/libcxx/include/__pstl/internal/parallel_backend_tbb.h b/lib/libcxx/include/__pstl/internal/parallel_backend_tbb.h new file mode 100644 index 0000000000..6a9a05ddd6 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/parallel_backend_tbb.h @@ -0,0 +1,1295 @@ +// -*- 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 _PSTL_PARALLEL_BACKEND_TBB_H +#define _PSTL_PARALLEL_BACKEND_TBB_H + +#include <__assert> +#include <__config> +#include +#include + +#include "parallel_backend_utils.h" + +// Bring in minimal required subset of Intel TBB +#include +#include +#include +#include +#include +#include +#include +#include + +#if TBB_INTERFACE_VERSION < 10000 +# error Intel(R) Threading Building Blocks 2018 is required; older versions are not supported. +#endif + +namespace __pstl +{ +namespace __tbb_backend +{ + +//! Raw memory buffer with automatic freeing and no exceptions. +/** Some of our algorithms need to start with raw memory buffer, +not an initialize array, because initialization/destruction +would make the span be at least O(N). */ +// tbb::allocator can improve performance in some cases. +template +class __buffer +{ + tbb::tbb_allocator<_Tp> _M_allocator; + _Tp* _M_ptr; + const std::size_t _M_buf_size; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + //! Try to obtain buffer of given size to store objects of _Tp type + __buffer(std::size_t n) : _M_allocator(), _M_ptr(_M_allocator.allocate(n)), _M_buf_size(n) {} + //! True if buffer was successfully obtained, zero otherwise. + operator bool() const { return _M_ptr != NULL; } + //! Return pointer to buffer, or NULL if buffer could not be obtained. + _Tp* + get() const + { + return _M_ptr; + } + //! Destroy buffer + ~__buffer() { _M_allocator.deallocate(_M_ptr, _M_buf_size); } +}; + +// Wrapper for tbb::task +inline void +__cancel_execution() +{ +#if TBB_INTERFACE_VERSION <= 12000 + tbb::task::self().group()->cancel_group_execution(); +#else + tbb::task::current_context()->cancel_group_execution(); +#endif +} + +//------------------------------------------------------------------------ +// parallel_for +//------------------------------------------------------------------------ + +template +class __parallel_for_body +{ + public: + __parallel_for_body(const _RealBody& __body) : _M_body(__body) {} + __parallel_for_body(const __parallel_for_body& __body) : _M_body(__body._M_body) {} + void + operator()(const tbb::blocked_range<_Index>& __range) const + { + _M_body(__range.begin(), __range.end()); + } + + private: + _RealBody _M_body; +}; + +//! Evaluation of brick f[i,j) for each subrange [i,j) of [first,last) +// wrapper over tbb::parallel_for +template +void +__parallel_for(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +{ + tbb::this_task_arena::isolate([=]() { + tbb::parallel_for(tbb::blocked_range<_Index>(__first, __last), __parallel_for_body<_Index, _Fp>(__f)); + }); +} + +//! Evaluation of brick f[i,j) for each subrange [i,j) of [first,last) +// wrapper over tbb::parallel_reduce +template +_Value +__parallel_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction& __reduction) +{ + return tbb::this_task_arena::isolate([__first, __last, &__identity, &__real_body, &__reduction]() -> _Value { + return tbb::parallel_reduce( + tbb::blocked_range<_Index>(__first, __last), __identity, + [__real_body](const tbb::blocked_range<_Index>& __r, const _Value& __value) -> _Value { + return __real_body(__r.begin(), __r.end(), __value); + }, + __reduction); + }); +} + +//------------------------------------------------------------------------ +// parallel_transform_reduce +// +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// u(i) returns f(i,i+1,identity) for a hypothetical left identity element of r +// c(x,y) combines values x and y that were the result of r or u +//------------------------------------------------------------------------ + +template +struct __par_trans_red_body +{ + alignas(_Tp) char _M_sum_storage[sizeof(_Tp)]; // Holds generalized non-commutative sum when has_sum==true + _Rp _M_brick_reduce; // Most likely to have non-empty layout + _Up _M_u; + _Cp _M_combine; + bool _M_has_sum; // Put last to minimize size of class + _Tp& + sum() + { + __TBB_ASSERT(_M_has_sum, "sum expected"); + return *(_Tp*)_M_sum_storage; + } + __par_trans_red_body(_Up __u, _Tp __init, _Cp __c, _Rp __r) + : _M_brick_reduce(__r), _M_u(__u), _M_combine(__c), _M_has_sum(true) + { + new (_M_sum_storage) _Tp(__init); + } + + __par_trans_red_body(__par_trans_red_body& __left, tbb::split) + : _M_brick_reduce(__left._M_brick_reduce), _M_u(__left._M_u), _M_combine(__left._M_combine), _M_has_sum(false) + { + } + + ~__par_trans_red_body() + { + // 17.6.5.12 tells us to not worry about catching exceptions from destructors. + if (_M_has_sum) + sum().~_Tp(); + } + + void + join(__par_trans_red_body& __rhs) + { + sum() = _M_combine(sum(), __rhs.sum()); + } + + void + operator()(const tbb::blocked_range<_Index>& __range) + { + _Index __i = __range.begin(); + _Index __j = __range.end(); + if (!_M_has_sum) + { + __TBB_ASSERT(__range.size() > 1, "there should be at least 2 elements"); + new (&_M_sum_storage) + _Tp(_M_combine(_M_u(__i), _M_u(__i + 1))); // The condition i+1 < j is provided by the grain size of 3 + _M_has_sum = true; + std::advance(__i, 2); + if (__i == __j) + return; + } + sum() = _M_brick_reduce(__i, __j, sum()); + } +}; + +template +_Tp +__parallel_transform_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce) +{ + __tbb_backend::__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce); + // The grain size of 3 is used in order to provide mininum 2 elements for each body + tbb::this_task_arena::isolate( + [__first, __last, &__body]() { tbb::parallel_reduce(tbb::blocked_range<_Index>(__first, __last, 3), __body); }); + return __body.sum(); +} + +//------------------------------------------------------------------------ +// parallel_scan +//------------------------------------------------------------------------ + +template +class __trans_scan_body +{ + alignas(_Tp) char _M_sum_storage[sizeof(_Tp)]; // Holds generalized non-commutative sum when has_sum==true + _Rp _M_brick_reduce; // Most likely to have non-empty layout + _Up _M_u; + _Cp _M_combine; + _Sp _M_scan; + bool _M_has_sum; // Put last to minimize size of class + public: + __trans_scan_body(_Up __u, _Tp __init, _Cp __combine, _Rp __reduce, _Sp __scan) + : _M_brick_reduce(__reduce), _M_u(__u), _M_combine(__combine), _M_scan(__scan), _M_has_sum(true) + { + new (_M_sum_storage) _Tp(__init); + } + + __trans_scan_body(__trans_scan_body& __b, tbb::split) + : _M_brick_reduce(__b._M_brick_reduce), _M_u(__b._M_u), _M_combine(__b._M_combine), _M_scan(__b._M_scan), + _M_has_sum(false) + { + } + + ~__trans_scan_body() + { + // 17.6.5.12 tells us to not worry about catching exceptions from destructors. + if (_M_has_sum) + sum().~_Tp(); + } + + _Tp& + sum() const + { + __TBB_ASSERT(_M_has_sum, "sum expected"); + return *const_cast<_Tp*>(reinterpret_cast<_Tp const*>(_M_sum_storage)); + } + + void + operator()(const tbb::blocked_range<_Index>& __range, tbb::pre_scan_tag) + { + _Index __i = __range.begin(); + _Index __j = __range.end(); + if (!_M_has_sum) + { + new (&_M_sum_storage) _Tp(_M_u(__i)); + _M_has_sum = true; + ++__i; + if (__i == __j) + return; + } + sum() = _M_brick_reduce(__i, __j, sum()); + } + + void + operator()(const tbb::blocked_range<_Index>& __range, tbb::final_scan_tag) + { + sum() = _M_scan(__range.begin(), __range.end(), sum()); + } + + void + reverse_join(__trans_scan_body& __a) + { + if (_M_has_sum) + { + sum() = _M_combine(__a.sum(), sum()); + } + else + { + new (&_M_sum_storage) _Tp(__a.sum()); + _M_has_sum = true; + } + } + + void + assign(__trans_scan_body& __b) + { + sum() = __b.sum(); + } +}; + +template +_Index +__split(_Index __m) +{ + _Index __k = 1; + while (2 * __k < __m) + __k *= 2; + return __k; +} + +//------------------------------------------------------------------------ +// __parallel_strict_scan +//------------------------------------------------------------------------ + +template +void +__upsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Rp __reduce, _Cp __combine) +{ + if (__m == 1) + __r[0] = __reduce(__i * __tilesize, __lastsize); + else + { + _Index __k = __split(__m); + tbb::parallel_invoke( + [=] { __tbb_backend::__upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); }, + [=] { + __tbb_backend::__upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); + }); + if (__m == 2 * __k) + __r[__m - 1] = __combine(__r[__k - 1], __r[__m - 1]); + } +} + +template +void +__downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Tp __initial, _Cp __combine, + _Sp __scan) +{ + if (__m == 1) + __scan(__i * __tilesize, __lastsize, __initial); + else + { + const _Index __k = __split(__m); + tbb::parallel_invoke( + [=] { __tbb_backend::__downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); }, + // Assumes that __combine never throws. + //TODO: Consider adding a requirement for user functors to be constant. + [=, &__combine] { + __tbb_backend::__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, + __combine(__initial, __r[__k - 1]), __combine, __scan); + }); + } +} + +// Adapted from Intel(R) Cilk(TM) version from cilkpub. +// Let i:len denote a counted interval of length n starting at i. s denotes a generalized-sum value. +// Expected actions of the functors are: +// reduce(i,len) -> s -- return reduction value of i:len. +// combine(s1,s2) -> s -- return merged sum +// apex(s) -- do any processing necessary between reduce and scan. +// scan(i,len,initial) -- perform scan over i:len starting with initial. +// The initial range 0:n is partitioned into consecutive subranges. +// reduce and scan are each called exactly once per subrange. +// Thus callers can rely upon side effects in reduce. +// combine must not throw an exception. +// apex is called exactly once, after all calls to reduce and before all calls to scan. +// For example, it's useful for allocating a __buffer used by scan but whose size is the sum of all reduction values. +// T must have a trivial constructor and destructor. +template +void +__parallel_strict_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + tbb::this_task_arena::isolate([=, &__combine]() { + if (__n > 1) + { + _Index __p = tbb::this_task_arena::max_concurrency(); + const _Index __slack = 4; + _Index __tilesize = (__n - 1) / (__slack * __p) + 1; + _Index __m = (__n - 1) / __tilesize; + __buffer<_Tp> __buf(__m + 1); + _Tp* __r = __buf.get(); + __tbb_backend::__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, + __combine); + + // When __apex is a no-op and __combine has no side effects, a good optimizer + // should be able to eliminate all code between here and __apex. + // Alternatively, provide a default value for __apex that can be + // recognized by metaprogramming that conditionlly executes the following. + size_t __k = __m + 1; + _Tp __t = __r[__k - 1]; + while ((__k &= __k - 1)) + __t = __combine(__r[__k - 1], __t); + __apex(__combine(__initial, __t)); + __tbb_backend::__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, + __combine, __scan); + return; + } + // Fewer than 2 elements in sequence, or out of memory. Handle has single block. + _Tp __sum = __initial; + if (__n) + __sum = __combine(__sum, __reduce(_Index(0), __n)); + __apex(__sum); + if (__n) + __scan(_Index(0), __n, __initial); + }); +} + +template +_Tp +__parallel_transform_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init, + _Cp __combine, _Rp __brick_reduce, _Sp __scan) +{ + __trans_scan_body<_Index, _Up, _Tp, _Cp, _Rp, _Sp> __body(__u, __init, __combine, __brick_reduce, __scan); + auto __range = tbb::blocked_range<_Index>(0, __n); + tbb::this_task_arena::isolate([__range, &__body]() { tbb::parallel_scan(__range, __body); }); + return __body.sum(); +} + +//------------------------------------------------------------------------ +// parallel_stable_sort +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// stable_sort utilities +// +// These are used by parallel implementations but do not depend on them. +//------------------------------------------------------------------------ +#define _PSTL_MERGE_CUT_OFF 2000 + +template +class __func_task; +template +class __root_task; + +#if TBB_INTERFACE_VERSION <= 12000 +class __task : public tbb::task +{ + public: + template + __task* + make_continuation(_Fn&& __f) + { + return new (allocate_continuation()) __func_task::type>(std::forward<_Fn>(__f)); + } + + template + __task* + make_child_of(__task* parent, _Fn&& __f) + { + return new (parent->allocate_child()) __func_task::type>(std::forward<_Fn>(__f)); + } + + template + __task* + make_additional_child_of(tbb::task* parent, _Fn&& __f) + { + return new (tbb::task::allocate_additional_child_of(*parent)) + __func_task::type>(std::forward<_Fn>(__f)); + } + + inline void + recycle_as_continuation() + { + tbb::task::recycle_as_continuation(); + } + + inline void + recycle_as_child_of(__task* parent) + { + tbb::task::recycle_as_child_of(*parent); + } + + inline void + spawn(__task* __t) + { + tbb::task::spawn(*__t); + } + + template + static inline void + spawn_root_and_wait(__root_task<_Fn>& __root) + { + tbb::task::spawn_root_and_wait(*__root._M_task); + } +}; + +template +class __func_task : public __task +{ + _Func _M_func; + + tbb::task* + execute() + { + return _M_func(this); + }; + + public: + template + __func_task(_Fn&& __f) : _M_func{std::forward<_Fn>(__f)} + { + } + + _Func& + body() + { + return _M_func; + } +}; + +template +class __root_task +{ + tbb::task* _M_task; + + public: + template + __root_task(Args&&... args) + : _M_task{new (tbb::task::allocate_root()) __func_task<_Func>{_Func(std::forward(args)...)}} + { + } + + friend class __task; + friend class __func_task<_Func>; +}; + +#else // TBB_INTERFACE_VERSION <= 12000 +class __task : public tbb::detail::d1::task +{ + protected: + tbb::detail::d1::small_object_allocator _M_allocator{}; + tbb::detail::d1::execution_data* _M_execute_data{}; + __task* _M_parent{}; + std::atomic _M_refcount{}; + bool _M_recycle{}; + + template + __task* + allocate_func_task(_Fn&& __f) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_M_execute_data != nullptr, ""); + tbb::detail::d1::small_object_allocator __alloc{}; + auto __t = + __alloc.new_object<__func_task::type>>(*_M_execute_data, std::forward<_Fn>(__f)); + __t->_M_allocator = __alloc; + return __t; + } + + public: + __task* + parent() + { + return _M_parent; + } + + void + set_ref_count(int __n) + { + _M_refcount.store(__n, std::memory_order_release); + } + + template + __task* + make_continuation(_Fn&& __f) + { + auto __t = allocate_func_task(std::forward<_Fn&&>(__f)); + __t->_M_parent = _M_parent; + _M_parent = nullptr; + return __t; + } + + template + __task* + make_child_of(__task* __parent, _Fn&& __f) + { + auto __t = allocate_func_task(std::forward<_Fn&&>(__f)); + __t->_M_parent = __parent; + return __t; + } + + template + __task* + make_additional_child_of(__task* __parent, _Fn&& __f) + { + auto __t = make_child_of(__parent, std::forward<_Fn>(__f)); + _LIBCPP_ASSERT_UNCATEGORIZED(__parent->_M_refcount.load(std::memory_order_relaxed) > 0, ""); + ++__parent->_M_refcount; + return __t; + } + + inline void + recycle_as_continuation() + { + _M_recycle = true; + } + + inline void + recycle_as_child_of(__task* parent) + { + _M_recycle = true; + _M_parent = parent; + } + + inline void + spawn(__task* __t) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_M_execute_data != nullptr, ""); + tbb::detail::d1::spawn(*__t, *_M_execute_data->context); + } + + template + static inline void + spawn_root_and_wait(__root_task<_Fn>& __root) + { + tbb::detail::d1::execute_and_wait(*__root._M_func_task, __root._M_context, __root._M_wait_object, + __root._M_context); + } + + template + friend class __func_task; +}; + +template +class __func_task : public __task +{ + _Func _M_func; + + __task* + execute(tbb::detail::d1::execution_data& __ed) override + { + _M_execute_data = &__ed; + _M_recycle = false; + __task* __next = _M_func(this); + return finalize(__next); + }; + + __task* + cancel(tbb::detail::d1::execution_data& __ed) override + { + return finalize(nullptr); + } + + __task* + finalize(__task* __next) + { + bool __recycle = _M_recycle; + _M_recycle = false; + + if (__recycle) + { + return __next; + } + + auto __parent = _M_parent; + auto __alloc = _M_allocator; + auto __ed = _M_execute_data; + + this->~__func_task(); + + _LIBCPP_ASSERT_UNCATEGORIZED(__parent != nullptr, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__parent->_M_refcount.load(std::memory_order_relaxed) > 0, ""); + if (--__parent->_M_refcount == 0) + { + _LIBCPP_ASSERT_UNCATEGORIZED(__next == nullptr, ""); + __alloc.deallocate(this, *__ed); + return __parent; + } + + return __next; + } + + friend class __root_task<_Func>; + + public: + template + __func_task(_Fn&& __f) : _M_func(std::forward<_Fn>(__f)) + { + } + + _Func& + body() + { + return _M_func; + } +}; + +template +class __root_task : public __task +{ + __task* + execute(tbb::detail::d1::execution_data& __ed) override + { + _M_wait_object.release(); + return nullptr; + }; + + __task* + cancel(tbb::detail::d1::execution_data& __ed) override + { + _M_wait_object.release(); + return nullptr; + } + + __func_task<_Func>* _M_func_task{}; + tbb::detail::d1::wait_context _M_wait_object{0}; + tbb::task_group_context _M_context{}; + + public: + template + __root_task(Args&&... args) : _M_wait_object{1} + { + tbb::detail::d1::small_object_allocator __alloc{}; + _M_func_task = __alloc.new_object<__func_task<_Func>>(_Func(std::forward(args)...)); + _M_func_task->_M_allocator = __alloc; + _M_func_task->_M_parent = this; + _M_refcount.store(1, std::memory_order_relaxed); + } + + friend class __task; +}; +#endif // TBB_INTERFACE_VERSION <= 12000 + +template +class __merge_func +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _ValueType; + + _RandomAccessIterator1 _M_x_beg; + _RandomAccessIterator2 _M_z_beg; + + _SizeType _M_xs, _M_xe; + _SizeType _M_ys, _M_ye; + _SizeType _M_zs; + _Compare _M_comp; + _LeafMerge _M_leaf_merge; + _SizeType _M_nsort; //number of elements to be sorted for partial_sort alforithm + + static const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + + bool _root; //means a task is merging root task + bool _x_orig; //"true" means X(or left ) subrange is in the original container; false - in the buffer + bool _y_orig; //"true" means Y(or right) subrange is in the original container; false - in the buffer + bool _split; //"true" means a merge task is a split task for parallel merging, the execution logic differs + + bool + is_partial() const + { + return _M_nsort > 0; + } + + struct __move_value + { + template + void + operator()(Iterator1 __x, Iterator2 __z) + { + *__z = std::move(*__x); + } + }; + + struct __move_value_construct + { + template + void + operator()(Iterator1 __x, Iterator2 __z) + { + ::new (std::addressof(*__z)) _ValueType(std::move(*__x)); + } + }; + + struct __move_range + { + template + Iterator2 + operator()(Iterator1 __first1, Iterator1 __last1, Iterator2 __first2) + { + if (__last1 - __first1 < __merge_cut_off) + return std::move(__first1, __last1, __first2); + + auto __n = __last1 - __first1; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first1, __first2](const tbb::blocked_range<_SizeType>& __range) { + std::move(__first1 + __range.begin(), __first1 + __range.end(), + __first2 + __range.begin()); + }); + return __first2 + __n; + } + }; + + struct __move_range_construct + { + template + Iterator2 + operator()(Iterator1 __first1, Iterator1 __last1, Iterator2 __first2) + { + if (__last1 - __first1 < __merge_cut_off) + { + for (; __first1 != __last1; ++__first1, ++__first2) + __move_value_construct()(__first1, __first2); + return __first2; + } + + auto __n = __last1 - __first1; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first1, __first2](const tbb::blocked_range<_SizeType>& __range) { + for (auto i = __range.begin(); i != __range.end(); ++i) + __move_value_construct()(__first1 + i, __first2 + i); + }); + return __first2 + __n; + } + }; + + struct __cleanup_range + { + template + void + operator()(Iterator __first, Iterator __last) + { + if (__last - __first < __merge_cut_off) + _Cleanup()(__first, __last); + else + { + auto __n = __last - __first; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first](const tbb::blocked_range<_SizeType>& __range) { + _Cleanup()(__first + __range.begin(), __first + __range.end()); + }); + } + } + }; + + public: + __merge_func(_SizeType __xs, _SizeType __xe, _SizeType __ys, _SizeType __ye, _SizeType __zs, _Compare __comp, + _Cleanup, _LeafMerge __leaf_merge, _SizeType __nsort, _RandomAccessIterator1 __x_beg, + _RandomAccessIterator2 __z_beg, bool __x_orig, bool __y_orig, bool __root) + : _M_xs(__xs), _M_xe(__xe), _M_ys(__ys), _M_ye(__ye), _M_zs(__zs), _M_x_beg(__x_beg), _M_z_beg(__z_beg), + _M_comp(__comp), _M_leaf_merge(__leaf_merge), _M_nsort(__nsort), _root(__root), + _x_orig(__x_orig), _y_orig(__y_orig), _split(false) + { + } + + bool + is_left(_SizeType __idx) const + { + return _M_xs == __idx; + } + + template + void + set_odd(IndexType __idx, bool __on_off) + { + if (is_left(__idx)) + _x_orig = __on_off; + else + _y_orig = __on_off; + } + + __task* + operator()(__task* __self); + + private: + __merge_func* + parent_merge(__task* __self) const + { + return _root ? nullptr : &static_cast<__func_task<__merge_func>*>(__self->parent())->body(); + } + bool + x_less_y() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0 && __ny > 0, ""); + + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!is_partial(), ""); + + if (_x_orig) + { + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_comp), ""); + return !_M_comp(*(_M_x_beg + _M_ys), *(_M_x_beg + _M_xe - 1)); + } + + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_comp), ""); + return !_M_comp(*(_M_z_beg + _M_zs + __nx), *(_M_z_beg + _M_zs + __nx - 1)); + } + void + move_x_range() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0 && __ny > 0, ""); + + if (_x_orig) + __move_range_construct()(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_z_beg + _M_zs); + else + { + __move_range()(_M_z_beg + _M_zs, _M_z_beg + _M_zs + __nx, _M_x_beg + _M_xs); + __cleanup_range()(_M_z_beg + _M_zs, _M_z_beg + _M_zs + __nx); + } + + _x_orig = !_x_orig; + } + void + move_y_range() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + if (_y_orig) + __move_range_construct()(_M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_z_beg + _M_zs + __nx); + else + { + __move_range()(_M_z_beg + _M_zs + __nx, _M_z_beg + _M_zs + __nx + __ny, _M_x_beg + _M_ys); + __cleanup_range()(_M_z_beg + _M_zs + __nx, _M_z_beg + _M_zs + __nx + __ny); + } + + _y_orig = !_y_orig; + } + __task* + merge_ranges(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); // two merged subrange must be lie into the same buffer + + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + const auto __n = __nx + __ny; + + // need to merge {x} and {y} + if (__n > __merge_cut_off) + return split_merging(__self); + + //merge to buffer + if (_x_orig) + { + _M_leaf_merge(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_z_beg + _M_zs, + _M_comp, __move_value_construct(), __move_value_construct(), __move_range_construct(), + __move_range_construct()); + _LIBCPP_ASSERT_UNCATEGORIZED(parent_merge(__self), ""); //not root merging task + } + //merge to "origin" + else + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + + _LIBCPP_ASSERT_UNCATEGORIZED( + is_partial() || std::is_sorted(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED( + is_partial() || std::is_sorted(_M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_comp), ""); + + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + _M_leaf_merge(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_x_beg + _M_zs, + _M_comp, __move_value(), __move_value(), __move_range(), __move_range()); + + __cleanup_range()(_M_z_beg + _M_xs, _M_z_beg + _M_xe); + __cleanup_range()(_M_z_beg + _M_ys, _M_z_beg + _M_ye); + } + return nullptr; + } + + __task* + process_ranges(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!_split, ""); + + auto p = parent_merge(__self); + + if (!p) + { //root merging task + + //optimization, just for sort algorithm, //{x} <= {y} + if (!is_partial() && x_less_y()) //we have a solution + { + if (!_x_orig) + { //we have to move the solution to the origin + move_x_range(); //parallel moving + move_y_range(); //parallel moving + } + return nullptr; + } + //else: if we have data in the origin, + //we have to move data to the buffer for final merging into the origin. + if (_x_orig) + { + move_x_range(); //parallel moving + move_y_range(); //parallel moving + } + // need to merge {x} and {y}. + return merge_ranges(__self); + } + //else: not root merging task (parent_merge() == NULL) + //optimization, just for sort algorithm, //{x} <= {y} + if (!is_partial() && x_less_y()) + { + const auto id_range = _M_zs; + p->set_odd(id_range, _x_orig); + return nullptr; + } + //else: we have to revert "_x(y)_orig" flag of the parent merging task + const auto id_range = _M_zs; + p->set_odd(id_range, !_x_orig); + + return merge_ranges(__self); + } + + //splitting as merge task into 2 of the same level + __task* + split_merging(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + _SizeType __xm{}; + _SizeType __ym{}; + if (__nx < __ny) + { + __ym = _M_ys + __ny / 2; + + if (_x_orig) + __xm = std::upper_bound(_M_x_beg + _M_xs, _M_x_beg + _M_xe, *(_M_x_beg + __ym), _M_comp) - _M_x_beg; + else + __xm = std::upper_bound(_M_z_beg + _M_xs, _M_z_beg + _M_xe, *(_M_z_beg + __ym), _M_comp) - _M_z_beg; + } + else + { + __xm = _M_xs + __nx / 2; + + if (_y_orig) + __ym = std::lower_bound(_M_x_beg + _M_ys, _M_x_beg + _M_ye, *(_M_x_beg + __xm), _M_comp) - _M_x_beg; + else + __ym = std::lower_bound(_M_z_beg + _M_ys, _M_z_beg + _M_ye, *(_M_z_beg + __xm), _M_comp) - _M_z_beg; + } + + auto __zm = _M_zs + ((__xm - _M_xs) + (__ym - _M_ys)); + __merge_func __right_func(__xm, _M_xe, __ym, _M_ye, __zm, _M_comp, _Cleanup(), _M_leaf_merge, _M_nsort, + _M_x_beg, _M_z_beg, _x_orig, _y_orig, _root); + __right_func._split = true; + auto __merge_task = __self->make_additional_child_of(__self->parent(), std::move(__right_func)); + __self->spawn(__merge_task); + __self->recycle_as_continuation(); + + _M_xe = __xm; + _M_ye = __ym; + _split = true; + + return __self; + } +}; + +template +__task* +__merge_func<_RandomAccessIterator1, _RandomAccessIterator2, __M_Compare, _Cleanup, _LeafMerge>:: +operator()(__task* __self) +{ + //a. split merge task into 2 of the same level; the special logic, + //without processing(process_ranges) adjacent sub-ranges x and y + if (_split) + return merge_ranges(__self); + + //b. General merging of adjacent sub-ranges x and y (with optimization in case of {x} <= {y} ) + + //1. x and y are in the even buffer + //2. x and y are in the odd buffer + if (_x_orig == _y_orig) + return process_ranges(__self); + + //3. x is in even buffer, y is in the odd buffer + //4. x is in odd buffer, y is in the even buffer + if (!parent_merge(__self)) + { //root merge task + if (_x_orig) + move_x_range(); + else + move_y_range(); + } + else + { + const _SizeType __nx = (_M_xe - _M_xs); + const _SizeType __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0, ""); + + if (__nx < __ny) + move_x_range(); + else + move_y_range(); + } + + return process_ranges(__self); +} + +template +class __stable_sort_func +{ + public: + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + + private: + _RandomAccessIterator1 _M_xs, _M_xe, _M_x_beg; + _RandomAccessIterator2 _M_zs, _M_z_beg; + _Compare _M_comp; + _LeafSort _M_leaf_sort; + bool _M_root; + _SizeType _M_nsort; //zero or number of elements to be sorted for partial_sort alforithm + + public: + __stable_sort_func(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __zs, + bool __root, _Compare __comp, _LeafSort __leaf_sort, _SizeType __nsort, + _RandomAccessIterator1 __x_beg, _RandomAccessIterator2 __z_beg) + : _M_xs(__xs), _M_xe(__xe), _M_x_beg(__x_beg), _M_zs(__zs), _M_z_beg(__z_beg), _M_comp(__comp), + _M_leaf_sort(__leaf_sort), _M_root(__root), _M_nsort(__nsort) + { + } + + __task* + operator()(__task* __self); +}; + +#define _PSTL_STABLE_SORT_CUT_OFF 500 + +template +__task* +__stable_sort_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _LeafSort>::operator()(__task* __self) +{ + typedef __merge_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, __utils::__serial_destroy, + __utils::__serial_move_merge> + _MergeTaskType; + + const _SizeType __n = _M_xe - _M_xs; + const _SizeType __nmerge = _M_nsort > 0 ? _M_nsort : __n; + const _SizeType __sort_cut_off = _PSTL_STABLE_SORT_CUT_OFF; + if (__n <= __sort_cut_off) + { + _M_leaf_sort(_M_xs, _M_xe, _M_comp); + _LIBCPP_ASSERT_UNCATEGORIZED(!_M_root, ""); + return nullptr; + } + + const _RandomAccessIterator1 __xm = _M_xs + __n / 2; + const _RandomAccessIterator2 __zm = _M_zs + (__xm - _M_xs); + const _RandomAccessIterator2 __ze = _M_zs + __n; + _MergeTaskType __m(_MergeTaskType(_M_xs - _M_x_beg, __xm - _M_x_beg, __xm - _M_x_beg, _M_xe - _M_x_beg, + _M_zs - _M_z_beg, _M_comp, __utils::__serial_destroy(), + __utils::__serial_move_merge(__nmerge), _M_nsort, _M_x_beg, _M_z_beg, + /*x_orig*/ true, /*y_orig*/ true, /*root*/ _M_root)); + auto __parent = __self->make_continuation(std::move(__m)); + __parent->set_ref_count(2); + auto __right = __self->make_child_of( + __parent, __stable_sort_func(__xm, _M_xe, __zm, false, _M_comp, _M_leaf_sort, _M_nsort, _M_x_beg, _M_z_beg)); + __self->spawn(__right); + __self->recycle_as_child_of(__parent); + _M_root = false; + _M_xe = __xm; + + return __self; +} + +template +void +__parallel_stable_sort(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __xs, + _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, std::size_t __nsort = 0) +{ + tbb::this_task_arena::isolate([=, &__nsort]() { + //sorting based on task tree and parallel merge + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _ValueType; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + const _DifferenceType __n = __xe - __xs; + if (__nsort == __n) + __nsort = 0; // 'partial_sort' becames 'sort' + + const _DifferenceType __sort_cut_off = _PSTL_STABLE_SORT_CUT_OFF; + if (__n > __sort_cut_off) + { + __buffer<_ValueType> __buf(__n); + __root_task<__stable_sort_func<_RandomAccessIterator, _ValueType*, _Compare, _LeafSort>> __root{ + __xs, __xe, __buf.get(), true, __comp, __leaf_sort, __nsort, __xs, __buf.get()}; + __task::spawn_root_and_wait(__root); + return; + } + //serial sort + __leaf_sort(__xs, __xe, __comp); + }); +} + +//------------------------------------------------------------------------ +// parallel_merge +//------------------------------------------------------------------------ +template +class __merge_func_static +{ + _RandomAccessIterator1 _M_xs, _M_xe; + _RandomAccessIterator2 _M_ys, _M_ye; + _RandomAccessIterator3 _M_zs; + _Compare _M_comp; + _LeafMerge _M_leaf_merge; + + public: + __merge_func_static(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, + _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, + _LeafMerge __leaf_merge) + : _M_xs(__xs), _M_xe(__xe), _M_ys(__ys), _M_ye(__ye), _M_zs(__zs), _M_comp(__comp), _M_leaf_merge(__leaf_merge) + { + } + + __task* + operator()(__task* __self); +}; + +//TODO: consider usage of parallel_for with a custom blocked_range +template +__task* +__merge_func_static<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3, __M_Compare, _LeafMerge>:: +operator()(__task* __self) +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + const _SizeType __n = (_M_xe - _M_xs) + (_M_ye - _M_ys); + const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + if (__n <= __merge_cut_off) + { + _M_leaf_merge(_M_xs, _M_xe, _M_ys, _M_ye, _M_zs, _M_comp); + return nullptr; + } + + _RandomAccessIterator1 __xm; + _RandomAccessIterator2 __ym; + if (_M_xe - _M_xs < _M_ye - _M_ys) + { + __ym = _M_ys + (_M_ye - _M_ys) / 2; + __xm = std::upper_bound(_M_xs, _M_xe, *__ym, _M_comp); + } + else + { + __xm = _M_xs + (_M_xe - _M_xs) / 2; + __ym = std::lower_bound(_M_ys, _M_ye, *__xm, _M_comp); + } + const _RandomAccessIterator3 __zm = _M_zs + ((__xm - _M_xs) + (__ym - _M_ys)); + auto __right = __self->make_additional_child_of( + __self->parent(), __merge_func_static(__xm, _M_xe, __ym, _M_ye, __zm, _M_comp, _M_leaf_merge)); + __self->spawn(__right); + __self->recycle_as_continuation(); + _M_xe = __xm; + _M_ye = __ym; + + return __self; +} + +template +void +__parallel_merge(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + const _SizeType __n = (__xe - __xs) + (__ye - __ys); + const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + if (__n <= __merge_cut_off) + { + // Fall back on serial merge + __leaf_merge(__xs, __xe, __ys, __ye, __zs, __comp); + } + else + { + tbb::this_task_arena::isolate([=]() { + typedef __merge_func_static<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3, + _Compare, _LeafMerge> + _TaskType; + __root_task<_TaskType> __root{__xs, __xe, __ys, __ye, __zs, __comp, __leaf_merge}; + __task::spawn_root_and_wait(__root); + }); + } +} + +//------------------------------------------------------------------------ +// parallel_invoke +//------------------------------------------------------------------------ +template +void +__parallel_invoke(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + //TODO: a version of tbb::this_task_arena::isolate with variadic arguments pack should be added in the future + tbb::this_task_arena::isolate([&]() { tbb::parallel_invoke(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); }); +} + +} // namespace __tbb_backend +} // namespace __pstl + +#endif /* _PSTL_PARALLEL_BACKEND_TBB_H */ diff --git a/lib/libcxx/include/__pstl/internal/parallel_backend_utils.h b/lib/libcxx/include/__pstl/internal/parallel_backend_utils.h new file mode 100644 index 0000000000..8adcdb71f8 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/parallel_backend_utils.h @@ -0,0 +1,260 @@ +// -*- 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 _PSTL_PARALLEL_BACKEND_UTILS_H +#define _PSTL_PARALLEL_BACKEND_UTILS_H + +#include <__assert> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> + +#include "utils.h" + +namespace __pstl +{ + +namespace __utils +{ + +//! Destroy sequence [xs,xe) +struct __serial_destroy +{ + template + void + operator()(_RandomAccessIterator __zs, _RandomAccessIterator __ze) + { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _ValueType; + while (__zs != __ze) + { + --__ze; + (*__ze).~_ValueType(); + } + } +}; + +//! Merge sequences [__xs,__xe) and [__ys,__ye) to output sequence [__zs,(__xe-__xs)+(__ye-__ys)), using std::move +struct __serial_move_merge +{ + const std::size_t _M_nmerge; + + explicit __serial_move_merge(std::size_t __nmerge) : _M_nmerge(__nmerge) {} + template + void + operator()(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, + _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, _MoveValueX __move_value_x, + _MoveValueY __move_value_y, _MoveSequenceX __move_sequence_x, _MoveSequenceY __move_sequence_y) + { + constexpr bool __same_move_val = std::is_same<_MoveValueX, _MoveValueY>::value; + constexpr bool __same_move_seq = std::is_same<_MoveSequenceX, _MoveSequenceY>::value; + + auto __n = _M_nmerge; + _LIBCPP_ASSERT_UNCATEGORIZED(__n > 0, ""); + + auto __nx = __xe - __xs; + //auto __ny = __ye - __ys; + _RandomAccessIterator3 __zs_beg = __zs; + + if (__xs != __xe) + { + if (__ys != __ye) + { + for (;;) + { + if (__comp(*__ys, *__xs)) + { + const auto __i = __zs - __zs_beg; + if (__i < __nx) + __move_value_x(__ys, __zs); + else + __move_value_y(__ys, __zs); + ++__zs, --__n; + if (++__ys == __ye) + { + break; + } + else if (__n == 0) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + __zs = __move_sequence_x(__ys, __ye, __zs); + else + __zs = __move_sequence_y(__ys, __ye, __zs); + break; + } + } + else + { + const auto __i = __zs - __zs_beg; + if (__same_move_val || __i < __nx) + __move_value_x(__xs, __zs); + else + __move_value_y(__xs, __zs); + ++__zs, --__n; + if (++__xs == __xe) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + __move_sequence_x(__ys, __ye, __zs); + else + __move_sequence_y(__ys, __ye, __zs); + return; + } + else if (__n == 0) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + { + __zs = __move_sequence_x(__xs, __xe, __zs); + __move_sequence_x(__ys, __ye, __zs); + } + else + { + __zs = __move_sequence_y(__xs, __xe, __zs); + __move_sequence_y(__ys, __ye, __zs); + } + return; + } + } + } + } + __ys = __xs; + __ye = __xe; + } + const auto __i = __zs - __zs_beg; + if (__same_move_seq || __i < __nx) + __move_sequence_x(__ys, __ye, __zs); + else + __move_sequence_y(__ys, __ye, __zs); + } +}; + +template +_OutputIterator +__set_union_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1; ++__result) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + if (__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first2); + ++__first2; + } + else + { + ::new (std::addressof(*__result)) _Tp(*__first1); + if (!__comp(*__first1, *__first2)) + ++__first2; + ++__first1; + } + } + return __cc_range(__first2, __last2, __result); +} + +template +_OutputIterator +__set_intersection_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1 && __first2 != __last2;) + { + if (__comp(*__first1, *__first2)) + ++__first1; + else + { + if (!__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + ++__first2; + } + } + return __result; +} + +template +_OutputIterator +__set_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1;) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + + if (__comp(*__first1, *__first2)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + else + { + if (!__comp(*__first2, *__first1)) + ++__first1; + ++__first2; + } + } + return __result; +} +template +_OutputIterator +__set_symmetric_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1;) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + + if (__comp(*__first1, *__first2)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + else + { + if (__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first2); + ++__result; + } + else + ++__first1; + ++__first2; + } + } + return __cc_range(__first2, __last2, __result); +} + +} // namespace __utils +} // namespace __pstl + +#endif /* _PSTL_PARALLEL_BACKEND_UTILS_H */ diff --git a/lib/libcxx/include/__pstl/internal/unseq_backend_simd.h b/lib/libcxx/include/__pstl/internal/unseq_backend_simd.h new file mode 100644 index 0000000000..c64c178471 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/unseq_backend_simd.h @@ -0,0 +1,697 @@ +// -*- 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 _PSTL_UNSEQ_BACKEND_SIMD_H +#define _PSTL_UNSEQ_BACKEND_SIMD_H + +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_same.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include +#include + +#include <__pstl/internal/utils.h> + +// This header defines the minimum set of vector routines required +// to support parallel STL. + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl +{ +namespace __unseq_backend +{ + +// Expect vector width up to 64 (or 512 bit) +const std::size_t __lane_size = 64; + +template +_LIBCPP_HIDE_FROM_ABI _Iterator +__simd_walk_1(_Iterator __first, _DifferenceType __n, _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first[__i]); + + return __first + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI _Iterator2 +__simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i]); + return __first2 + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI _Iterator3 +__simd_walk_3(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, + _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i], __first3[__i]); + return __first3 + __n; +} + +// TODO: check whether __simd_first() can be used here +template +_LIBCPP_HIDE_FROM_ABI bool +__simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept +{ + _DifferenceType __block_size = 4 < __n ? 4 : __n; + const _Index __last = __first + __n; + while (__last != __first) + { + int32_t __flag = 1; + _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag) + for (_DifferenceType __i = 0; __i < __block_size; ++__i) + if (__pred(*(__first + __i))) + __flag = 0; + if (!__flag) + return true; + + __first += __block_size; + if (__last - __first >= __block_size << 1) + { + // Double the block _Size. Any unnecessary iterations can be amortized against work done so far. + __block_size <<= 1; + } + else + { + __block_size = __last - __first; + } + } + return false; +} + +template +_LIBCPP_HIDE_FROM_ABI std::pair<_Index1, _Index2> +__simd_first(_Index1 __first1, _DifferenceType __n, _Index2 __first2, _Pred __pred) noexcept +{ + const _Index1 __last1 = __first1 + __n; + const _Index2 __last2 = __first2 + __n; + // Experiments show good block sizes like this + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__last1 - __first1 >= __block_size) + { + _DifferenceType __found = 0; + _DifferenceType __i; + _PSTL_PRAGMA_SIMD_REDUCTION(| + : __found) for (__i = 0; __i < __block_size; ++__i) + { + const _DifferenceType __t = __pred(__first1[__i], __first2[__i]); + __lane[__i] = __t; + __found |= __t; + } + if (__found) + { + _DifferenceType __i2; + // This will vectorize + for (__i2 = 0; __i2 < __block_size; ++__i2) + { + if (__lane[__i2]) + break; + } + return std::make_pair(__first1 + __i2, __first2 + __i2); + } + __first1 += __block_size; + __first2 += __block_size; + } + + //Keep remainder scalar + for (; __last1 != __first1; ++__first1, ++__first2) + if (__pred(*(__first1), *(__first2))) + return std::make_pair(__first1, __first2); + + return std::make_pair(__last1, __last2); +} + +template +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_count(_Index __index, _DifferenceType __n, _Pred __pred) noexcept +{ + _DifferenceType __count = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + if (__pred(*(__index + __i))) + ++__count; + + return __count; +} + +template +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_unique_copy(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, + _BinaryPredicate __pred) noexcept +{ + if (__n == 0) + return __result; + + _DifferenceType __cnt = 1; + __result[0] = __first[0]; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 1; __i < __n; ++__i) + { + if (!__pred(__first[__i], __first[__i - 1])) + { + __result[__cnt] = __first[__i]; + ++__cnt; + } + } + return __result + __cnt; +} + +template +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_assign(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, _Assigner __assigner) noexcept +{ + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __assigner(__first + __i, __result + __i); + return __result + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_copy_if(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __cnt = 0; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__pred(__first[__i])) + { + __result[__cnt] = __first[__i]; + ++__cnt; + } + } + return __result + __cnt; +} + +template +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_calc_mask_2(_InputIterator __first, _DifferenceType __n, bool* __mask, _BinaryPredicate __pred) noexcept +{ + _DifferenceType __count = 0; + + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + __mask[__i] = !__pred(__first[__i], __first[__i - 1]); + __count += __mask[__i]; + } + return __count; +} + +template +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_calc_mask_1(_InputIterator __first, _DifferenceType __n, bool* __mask, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __count = 0; + + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + __mask[__i] = __pred(__first[__i]); + __count += __mask[__i]; + } + return __count; +} + +template +_LIBCPP_HIDE_FROM_ABI void +__simd_copy_by_mask(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, bool* __mask, + _Assigner __assigner) noexcept +{ + _DifferenceType __cnt = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__mask[__i]) + { + { + __assigner(__first + __i, __result + __cnt); + ++__cnt; + } + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI void +__simd_partition_by_mask(_InputIterator __first, _DifferenceType __n, _OutputIterator1 __out_true, + _OutputIterator2 __out_false, bool* __mask) noexcept +{ + _DifferenceType __cnt_true = 0, __cnt_false = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__mask[__i]) + { + __out_true[__cnt_true] = __first[__i]; + ++__cnt_true; + } + else + { + __out_false[__cnt_false] = __first[__i]; + ++__cnt_false; + } + } +} + +template +_LIBCPP_HIDE_FROM_ABI _Index +__simd_generate_n(_Index __first, _DifferenceType __size, _Generator __g) noexcept +{ + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __size; ++__i) + __first[__i] = __g(); + return __first + __size; +} + +template +_LIBCPP_HIDE_FROM_ABI _Index +__simd_adjacent_find(_Index __first, _Index __last, _BinaryPredicate __pred, bool __or_semantic) noexcept +{ + if (__last - __first < 2) + return __last; + + typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; + _DifferenceType __i = 0; + + // Experiments show good block sizes like this + //TODO: to consider tuning block_size for various data types + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__last - __first >= __block_size) + { + _DifferenceType __found = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(| + : __found) for (__i = 0; __i < __block_size - 1; ++__i) + { + //TODO: to improve SIMD vectorization + const _DifferenceType __t = __pred(*(__first + __i), *(__first + __i + 1)); + __lane[__i] = __t; + __found |= __t; + } + + //Process a pair of elements on a boundary of a data block + if (__first + __block_size < __last && __pred(*(__first + __i), *(__first + __i + 1))) + __lane[__i] = __found = 1; + + if (__found) + { + if (__or_semantic) + return __first; + + // This will vectorize + for (__i = 0; __i < __block_size; ++__i) + if (__lane[__i]) + break; + return __first + __i; //As far as found is true a __result (__lane[__i] is true) is guaranteed + } + __first += __block_size; + } + //Process the rest elements + for (; __last - __first > 1; ++__first) + if (__pred(*__first, *(__first + 1))) + return __first; + + return __last; +} + +// It was created to reduce the code inside std::enable_if +template +using is_arithmetic_plus = std::integral_constant::value && + std::is_same<_BinaryOperation, std::plus<_Tp>>::value>; + +// Exclusive scan for "+" and arithmetic types +template +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation, /*Inclusive*/ std::false_type) +{ + _PSTL_PRAGMA_SIMD_SCAN(+ : __init) + for (_Size __i = 0; __i < __n; ++__i) + { + __result[__i] = __init; + _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(__init) + __init += __unary_op(__first[__i]); + } + return std::make_pair(__result + __n, __init); +} + +// As soon as we cannot call __binary_op in "combiner" we create a wrapper over _Tp to encapsulate __binary_op +template +struct _Combiner +{ + _Tp __value_; + _BinaryOp* __bin_op_; // Here is a pointer to function because of default ctor + + _LIBCPP_HIDE_FROM_ABI _Combiner() : __value_{}, __bin_op_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI + _Combiner(const _Tp& __value, const _BinaryOp* __bin_op) + : __value_(__value), __bin_op_(const_cast<_BinaryOp*>(__bin_op)) {} + _LIBCPP_HIDE_FROM_ABI _Combiner(const _Combiner& __obj) : __value_{}, __bin_op_(__obj.__bin_op) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(const _Combiner& __obj) + { + __value_ = (*__bin_op_)(__value_, __obj.__value_); + } +}; + +// Exclusive scan for other binary operations and types +template +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, /*Inclusive*/ std::false_type) +{ + typedef _Combiner<_Tp, _BinaryOperation> _CombinerType; + _CombinerType __combined_init{__init, &__binary_op}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__bin_op, _CombinerType) + _PSTL_PRAGMA_SIMD_SCAN(__bin_op : __combined_init) + for (_Size __i = 0; __i < __n; ++__i) + { + __result[__i] = __combined_init.__value_; + _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(__combined_init) + __combined_init.__value_ = __binary_op(__combined_init.__value_, __unary_op(__first[__i])); + } + return std::make_pair(__result + __n, __combined_init.__value_); +} + +// Inclusive scan for "+" and arithmetic types +template +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation, /*Inclusive*/ std::true_type) +{ + _PSTL_PRAGMA_SIMD_SCAN(+ : __init) + for (_Size __i = 0; __i < __n; ++__i) + { + __init += __unary_op(__first[__i]); + _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(__init) + __result[__i] = __init; + } + return std::make_pair(__result + __n, __init); +} + +// Inclusive scan for other binary operations and types +template +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, std::true_type) +{ + typedef _Combiner<_Tp, _BinaryOperation> _CombinerType; + _CombinerType __combined_init{__init, &__binary_op}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__bin_op, _CombinerType) + _PSTL_PRAGMA_SIMD_SCAN(__bin_op : __combined_init) + for (_Size __i = 0; __i < __n; ++__i) + { + __combined_init.__value_ = __binary_op(__combined_init.__value_, __unary_op(__first[__i])); + _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(__combined_init) + __result[__i] = __combined_init.__value_; + } + return std::make_pair(__result + __n, __combined_init.__value_); +} + +// [restriction] - std::iterator_traits<_ForwardIterator>::value_type should be DefaultConstructible. +// complexity [violation] - We will have at most (__n-1 + number_of_lanes) comparisons instead of at most __n-1. +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__simd_min_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcept +{ + if (__n == 0) + { + return __first; + } + + typedef typename std::iterator_traits<_ForwardIterator>::value_type _ValueType; + struct _ComplexType + { + _ValueType __min_val_; + _Size __min_ind_; + _Compare* __min_comp_; + + _LIBCPP_HIDE_FROM_ABI _ComplexType() : __min_val_{}, __min_ind_{}, __min_comp_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ValueType& __val, const _Compare* __comp) + : __min_val_(__val), __min_ind_(0), __min_comp_(const_cast<_Compare*>(__comp)) + { + } + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ComplexType& __obj) + : __min_val_(__obj.__min_val_), __min_ind_(__obj.__min_ind_), __min_comp_(__obj.__min_comp_) + { + } + + _PSTL_PRAGMA_DECLARE_SIMD + _LIBCPP_HIDE_FROM_ABI void + operator()(const _ComplexType& __obj) + { + if (!(*__min_comp_)(__min_val_, __obj.__min_val_) && + ((*__min_comp_)(__obj.__min_val_, __min_val_) || __obj.__min_ind_ - __min_ind_ < 0)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = __obj.__min_ind_; + } + } + }; + + _ComplexType __init{*__first, &__comp}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__min_func, _ComplexType) + + _PSTL_PRAGMA_SIMD_REDUCTION(__min_func : __init) + for (_Size __i = 1; __i < __n; ++__i) + { + const _ValueType __min_val = __init.__min_val_; + const _ValueType __current = __first[__i]; + if (__comp(__current, __min_val)) + { + __init.__min_val_ = __current; + __init.__min_ind_ = __i; + } + } + return __first + __init.__min_ind_; +} + +// [restriction] - std::iterator_traits<_ForwardIterator>::value_type should be DefaultConstructible. +// complexity [violation] - We will have at most (2*(__n-1) + 4*number_of_lanes) comparisons instead of at most [1.5*(__n-1)]. +template +_LIBCPP_HIDE_FROM_ABI std::pair<_ForwardIterator, _ForwardIterator> +__simd_minmax_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcept +{ + if (__n == 0) + { + return std::make_pair(__first, __first); + } + typedef typename std::iterator_traits<_ForwardIterator>::value_type _ValueType; + + struct _ComplexType + { + _ValueType __min_val_; + _ValueType __max_val_; + _Size __min_ind_; + _Size __max_ind_; + _Compare* __minmax_comp; + + _LIBCPP_HIDE_FROM_ABI _ComplexType() + : __min_val_{}, __max_val_{}, __min_ind_{}, __max_ind_{}, __minmax_comp(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _ComplexType( + const _ValueType& __min_val, const _ValueType& __max_val, const _Compare* __comp) + : __min_val_(__min_val), __max_val_(__max_val), __min_ind_(0), __max_ind_(0), + __minmax_comp(const_cast<_Compare*>(__comp)) + { + } + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ComplexType& __obj) + : __min_val_(__obj.__min_val_), __max_val_(__obj.__max_val_), __min_ind_(__obj.__min_ind_), + __max_ind_(__obj.__max_ind_), __minmax_comp(__obj.__minmax_comp) + { + } + + _LIBCPP_HIDE_FROM_ABI void + operator()(const _ComplexType& __obj) + { + // min + if ((*__minmax_comp)(__obj.__min_val_, __min_val_)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = __obj.__min_ind_; + } + else if (!(*__minmax_comp)(__min_val_, __obj.__min_val_)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = (__min_ind_ - __obj.__min_ind_ < 0) ? __min_ind_ : __obj.__min_ind_; + } + + // max + if ((*__minmax_comp)(__max_val_, __obj.__max_val_)) + { + __max_val_ = __obj.__max_val_; + __max_ind_ = __obj.__max_ind_; + } + else if (!(*__minmax_comp)(__obj.__max_val_, __max_val_)) + { + __max_val_ = __obj.__max_val_; + __max_ind_ = (__max_ind_ - __obj.__max_ind_ < 0) ? __obj.__max_ind_ : __max_ind_; + } + } + }; + + _ComplexType __init{*__first, *__first, &__comp}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__min_func, _ComplexType); + + _PSTL_PRAGMA_SIMD_REDUCTION(__min_func : __init) + for (_Size __i = 1; __i < __n; ++__i) + { + auto __min_val = __init.__min_val_; + auto __max_val = __init.__max_val_; + auto __current = __first + __i; + if (__comp(*__current, __min_val)) + { + __init.__min_val_ = *__current; + __init.__min_ind_ = __i; + } + else if (!__comp(*__current, __max_val)) + { + __init.__max_val_ = *__current; + __init.__max_ind_ = __i; + } + } + return std::make_pair(__first + __init.__min_ind_, __first + __init.__max_ind_); +} + +template +_LIBCPP_HIDE_FROM_ABI std::pair<_OutputIterator1, _OutputIterator2> +__simd_partition_copy(_InputIterator __first, _DifferenceType __n, _OutputIterator1 __out_true, + _OutputIterator2 __out_false, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __cnt_true = 0, __cnt_false = 0; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__pred(__first[__i])) + { + __out_true[__cnt_true] = __first[__i]; + ++__cnt_true; + } + else + { + __out_false[__cnt_false] = __first[__i]; + ++__cnt_false; + } + } + return std::make_pair(__out_true + __cnt_true, __out_false + __cnt_false); +} + +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator1 +__simd_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept +{ + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferencType; + + const _DifferencType __n1 = __last - __first; + const _DifferencType __n2 = __s_last - __s_first; + if (__n1 == 0 || __n2 == 0) + { + return __last; // according to the standard + } + + // Common case + // If first sequence larger than second then we'll run simd_first with parameters of first sequence. + // Otherwise, vice versa. + if (__n1 < __n2) + { + for (; __first != __last; ++__first) + { + if (__unseq_backend::__simd_or( + __s_first, __n2, + __internal::__equal_value_by_pred(*__first, __pred))) + { + return __first; + } + } + } + else + { + for (; __s_first != __s_last; ++__s_first) + { + const auto __result = __unseq_backend::__simd_first( + __first, _DifferencType(0), __n1, [__s_first, &__pred](_ForwardIterator1 __it, _DifferencType __i) { + return __pred(__it[__i], *__s_first); + }); + if (__result != __last) + { + return __result; + } + } + } + return __last; +} + +template +_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator +__simd_remove_if(_RandomAccessIterator __first, _DifferenceType __n, _UnaryPredicate __pred) noexcept +{ + // find first element we need to remove + auto __current = __unseq_backend::__simd_first( + __first, _DifferenceType(0), __n, + [&__pred](_RandomAccessIterator __it, _DifferenceType __i) { return __pred(__it[__i]); }); + __n -= __current - __first; + + // if we have in sequence only one element that pred(__current[1]) != false we can exit the function + if (__n < 2) + { + return __current; + } + + _DifferenceType __cnt = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 1; __i < __n; ++__i) + { + if (!__pred(__current[__i])) + { + __current[__cnt] = std::move(__current[__i]); + ++__cnt; + } + } + return __current + __cnt; +} +} // namespace __unseq_backend +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_UNSEQ_BACKEND_SIMD_H */ diff --git a/lib/libcxx/include/__pstl/internal/utils.h b/lib/libcxx/include/__pstl/internal/utils.h new file mode 100644 index 0000000000..92c8d48db5 --- /dev/null +++ b/lib/libcxx/include/__pstl/internal/utils.h @@ -0,0 +1,144 @@ +// -*- 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 _PSTL_UTILS_H +#define _PSTL_UTILS_H + +#include <__config> +#include <__exception/terminate.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace __internal { + +template +_LIBCPP_HIDE_FROM_ABI auto __except_handler(_Fp __f) -> decltype(__f()) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return __f(); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (const std::bad_alloc&) { + throw; // re-throw bad_alloc according to the standard [algorithms.parallel.exceptions] + } catch (...) { + std::terminate(); // Good bye according to the standard [algorithms.parallel.exceptions] + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS +} + +template +_LIBCPP_HIDE_FROM_ABI void __invoke_if(std::true_type, _Fp __f) { + __f(); +} + +template +_LIBCPP_HIDE_FROM_ABI void __invoke_if(std::false_type, _Fp) {} + +template +_LIBCPP_HIDE_FROM_ABI void __invoke_if_not(std::false_type, _Fp __f) { + __f(); +} + +template +_LIBCPP_HIDE_FROM_ABI void __invoke_if_not(std::true_type, _Fp) {} + +template +_LIBCPP_HIDE_FROM_ABI auto __invoke_if_else(std::true_type, _F1 __f1, _F2) -> decltype(__f1()) { + return __f1(); +} + +template +_LIBCPP_HIDE_FROM_ABI auto __invoke_if_else(std::false_type, _F1, _F2 __f2) -> decltype(__f2()) { + return __f2(); +} + +//! Unary operator that returns reference to its argument. +struct __no_op { + template + _LIBCPP_HIDE_FROM_ABI _Tp&& operator()(_Tp&& __a) const { + return std::forward<_Tp>(__a); + } +}; + +template +class __reorder_pred { + _Pred __pred_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __reorder_pred(_Pred __pred) : __pred_(__pred) {} + + template + _LIBCPP_HIDE_FROM_ABI bool operator()(_FTp&& __a, _STp&& __b) { + return __pred_(std::forward<_STp>(__b), std::forward<_FTp>(__a)); + } +}; + +//! Like a polymorphic lambda for pred(...,value) +template +class __equal_value_by_pred { + const _Tp& __value_; + _Predicate __pred_; + +public: + _LIBCPP_HIDE_FROM_ABI __equal_value_by_pred(const _Tp& __value, _Predicate __pred) + : __value_(__value), __pred_(__pred) {} + + template + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) { + return __pred_(std::forward<_Arg>(__arg), __value_); + } +}; + +//! Like a polymorphic lambda for ==value +template +class __equal_value { + const _Tp& __value_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __equal_value(const _Tp& __value) : __value_(__value) {} + + template + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) const { + return std::forward<_Arg>(__arg) == __value_; + } +}; + +//! Logical negation of ==value +template +class __not_equal_value { + const _Tp& __value_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __not_equal_value(const _Tp& __value) : __value_(__value) {} + + template + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) const { + return !(std::forward<_Arg>(__arg) == __value_); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__cmp_iterators_by_values(_ForwardIterator __a, _ForwardIterator __b, _Compare __comp) { + if (__a < __b) { // we should return closer iterator + return __comp(*__b, *__a) ? __b : __a; + } else { + return __comp(*__a, *__b) ? __a : __b; + } +} + +} // namespace __internal +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_UTILS_H */ diff --git a/lib/libcxx/src/format.cpp b/lib/libcxx/include/__pstl_algorithm similarity index 68% rename from lib/libcxx/src/format.cpp rename to lib/libcxx/include/__pstl_algorithm index 401cccf172..79c18385c5 100644 --- a/lib/libcxx/src/format.cpp +++ b/lib/libcxx/include/__pstl_algorithm @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -6,12 +7,9 @@ // //===----------------------------------------------------------------------===// -#include +#ifndef __PSTL_ALGORITHM +#define __PSTL_ALGORITHM -_LIBCPP_BEGIN_NAMESPACE_STD +#include -#ifndef _LIBCPP_INLINE_FORMAT_ERROR_DTOR -format_error::~format_error() noexcept = default; -#endif - -_LIBCPP_END_NAMESPACE_STD +#endif /* __PSTL_ALGORITHM */ diff --git a/lib/libcxx/src/utility.cpp b/lib/libcxx/include/__pstl_memory similarity index 74% rename from lib/libcxx/src/utility.cpp rename to lib/libcxx/include/__pstl_memory index 44433d11d7..12b7f5aa3c 100644 --- a/lib/libcxx/src/utility.cpp +++ b/lib/libcxx/include/__pstl_memory @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -6,10 +7,9 @@ // //===----------------------------------------------------------------------===// -#include +#ifndef __PSTL_MEMORY +#define __PSTL_MEMORY -_LIBCPP_BEGIN_NAMESPACE_STD +#include -const piecewise_construct_t piecewise_construct{}; - -_LIBCPP_END_NAMESPACE_STD +#endif /* __PSTL_MEMORY */ diff --git a/lib/libcxx/include/__support/solaris/floatingpoint.h b/lib/libcxx/include/__pstl_numeric similarity index 73% rename from lib/libcxx/include/__support/solaris/floatingpoint.h rename to lib/libcxx/include/__pstl_numeric index 5f1628fbe4..cf168ef705 100644 --- a/lib/libcxx/include/__support/solaris/floatingpoint.h +++ b/lib/libcxx/include/__pstl_numeric @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -6,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#define atof sun_atof -#define strtod sun_strtod -#include_next "floatingpoint.h" -#undef atof -#undef strtod +#ifndef __PSTL_NUMERIC +#define __PSTL_NUMERIC + +#include + +#endif /* __PSTL_NUMERIC */ diff --git a/lib/libcxx/include/__random/binomial_distribution.h b/lib/libcxx/include/__random/binomial_distribution.h index 7b0f055d50..18053c7d13 100644 --- a/lib/libcxx/include/__random/binomial_distribution.h +++ b/lib/libcxx/include/__random/binomial_distribution.h @@ -42,7 +42,7 @@ public: public: typedef binomial_distribution distribution_type; - explicit param_type(result_type __t = 1, double __p = 0.5); + _LIBCPP_HIDE_FROM_ABI explicit param_type(result_type __t = 1, double __p = 0.5); _LIBCPP_INLINE_VISIBILITY result_type t() const {return __t_;} @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/clamp_to_integral.h b/lib/libcxx/include/__random/clamp_to_integral.h index 7d44ff9cfc..c67d76d6e9 100644 --- a/lib/libcxx/include/__random/clamp_to_integral.h +++ b/lib/libcxx/include/__random/clamp_to_integral.h @@ -12,7 +12,6 @@ #include <__config> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -44,8 +43,8 @@ template _LIBCPP_INLINE_VISIBILITY _IntT __clamp_to_integral(_RealT __r) _NOEXCEPT { using _Lim = numeric_limits<_IntT>; - const _IntT _MaxVal = __max_representable_int_for_float<_IntT, _RealT>(); - if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) { + const _IntT __max_val = __max_representable_int_for_float<_IntT, _RealT>(); + if (__r >= ::nextafter(static_cast<_RealT>(__max_val), INFINITY)) { return _Lim::max(); } else if (__r <= _Lim::lowest()) { return _Lim::min(); diff --git a/lib/libcxx/include/__random/discard_block_engine.h b/lib/libcxx/include/__random/discard_block_engine.h index db33623d94..7bdcb6555c 100644 --- a/lib/libcxx/include/__random/discard_block_engine.h +++ b/lib/libcxx/include/__random/discard_block_engine.h @@ -11,10 +11,12 @@ #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -90,7 +92,7 @@ public: seed(_Sseq& __q) {__e_.seed(__q); __n_ = 0;} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} diff --git a/lib/libcxx/include/__random/discrete_distribution.h b/lib/libcxx/include/__random/discrete_distribution.h index 03f49ba872..a6546faae8 100644 --- a/lib/libcxx/include/__random/discrete_distribution.h +++ b/lib/libcxx/include/__random/discrete_distribution.h @@ -53,10 +53,10 @@ public: : __p_(__wl.begin(), __wl.end()) {__init();} #endif // _LIBCPP_CXX03_LANG template - param_type(size_t __nw, double __xmin, double __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, double __xmin, double __xmax, _UnaryOperation __fw); - vector probabilities() const; + _LIBCPP_HIDE_FROM_ABI vector probabilities() const; friend _LIBCPP_INLINE_VISIBILITY bool operator==(const param_type& __x, const param_type& __y) @@ -66,7 +66,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class discrete_distribution; @@ -115,7 +115,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/exponential_distribution.h b/lib/libcxx/include/__random/exponential_distribution.h index 8edf1ac3f6..b33b072eca 100644 --- a/lib/libcxx/include/__random/exponential_distribution.h +++ b/lib/libcxx/include/__random/exponential_distribution.h @@ -79,7 +79,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/extreme_value_distribution.h b/lib/libcxx/include/__random/extreme_value_distribution.h index b3cba39249..c583ec06a3 100644 --- a/lib/libcxx/include/__random/extreme_value_distribution.h +++ b/lib/libcxx/include/__random/extreme_value_distribution.h @@ -84,7 +84,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/fisher_f_distribution.h b/lib/libcxx/include/__random/fisher_f_distribution.h index b5479acb47..b757607bc4 100644 --- a/lib/libcxx/include/__random/fisher_f_distribution.h +++ b/lib/libcxx/include/__random/fisher_f_distribution.h @@ -82,7 +82,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/gamma_distribution.h b/lib/libcxx/include/__random/gamma_distribution.h index 0d7fc3f828..777f6b5c76 100644 --- a/lib/libcxx/include/__random/gamma_distribution.h +++ b/lib/libcxx/include/__random/gamma_distribution.h @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/generate_canonical.h b/lib/libcxx/include/__random/generate_canonical.h index 5fada6df59..5f0aa6fd85 100644 --- a/lib/libcxx/include/__random/generate_canonical.h +++ b/lib/libcxx/include/__random/generate_canonical.h @@ -30,20 +30,20 @@ template _LIBCPP_HIDE_FROM_ABI _RealType generate_canonical(_URNG& __g) { - const size_t _Dt = numeric_limits<_RealType>::digits; - const size_t __b = _Dt < __bits ? _Dt : __bits; + const size_t __dt = numeric_limits<_RealType>::digits; + const size_t __b = __dt < __bits ? __dt : __bits; #ifdef _LIBCPP_CXX03_LANG - const size_t __logR = __log2::value; + const size_t __log_r = __log2::value; #else - const size_t __logR = __log2::value; + const size_t __log_r = __log2::value; #endif - const size_t __k = __b / __logR + (__b % __logR != 0) + (__b == 0); - const _RealType _Rp = static_cast<_RealType>(_URNG::max() - _URNG::min()) + _RealType(1); - _RealType __base = _Rp; - _RealType _Sp = __g() - _URNG::min(); - for (size_t __i = 1; __i < __k; ++__i, __base *= _Rp) - _Sp += (__g() - _URNG::min()) * __base; - return _Sp / __base; + const size_t __k = __b / __log_r + (__b % __log_r != 0) + (__b == 0); + const _RealType __rp = static_cast<_RealType>(_URNG::max() - _URNG::min()) + _RealType(1); + _RealType __base = __rp; + _RealType __sp = __g() - _URNG::min(); + for (size_t __i = 1; __i < __k; ++__i, __base *= __rp) + __sp += (__g() - _URNG::min()) * __base; + return __sp / __base; } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__random/independent_bits_engine.h b/lib/libcxx/include/__random/independent_bits_engine.h index 151492a81b..a86c22157d 100644 --- a/lib/libcxx/include/__random/independent_bits_engine.h +++ b/lib/libcxx/include/__random/independent_bits_engine.h @@ -12,10 +12,13 @@ #include <__config> #include <__random/is_seed_sequence.h> #include <__random/log2.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -161,7 +164,7 @@ public: private: _LIBCPP_INLINE_VISIBILITY result_type __eval(false_type); - result_type __eval(true_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type); template _LIBCPP_INLINE_VISIBILITY @@ -196,7 +199,7 @@ template _UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { - result_type _Sp = 0; + result_type __sp = 0; for (size_t __k = 0; __k < __n0; ++__k) { _Engine_result_type __u; @@ -204,7 +207,7 @@ independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y0); - _Sp = static_cast(__lshift<__w0>(_Sp) + (__u & __mask0)); + __sp = static_cast(__lshift<__w0>(__sp) + (__u & __mask0)); } for (size_t __k = __n0; __k < __n; ++__k) { @@ -213,9 +216,9 @@ independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y1); - _Sp = static_cast(__lshift<__w0+1>(_Sp) + (__u & __mask1)); + __sp = static_cast(__lshift<__w0+1>(__sp) + (__u & __mask1)); } - return _Sp; + return __sp; } template diff --git a/lib/libcxx/include/__random/is_seed_sequence.h b/lib/libcxx/include/__random/is_seed_sequence.h index 3c82b2790b..06621c3cee 100644 --- a/lib/libcxx/include/__random/is_seed_sequence.h +++ b/lib/libcxx/include/__random/is_seed_sequence.h @@ -10,7 +10,9 @@ #define _LIBCPP___RANDOM_IS_SEED_SEQUENCE_H #include <__config> -#include +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__random/is_valid.h b/lib/libcxx/include/__random/is_valid.h index 1d65de00fb..113452bc5d 100644 --- a/lib/libcxx/include/__random/is_valid.h +++ b/lib/libcxx/include/__random/is_valid.h @@ -10,8 +10,12 @@ #define _LIBCPP___RANDOM_IS_VALID_H #include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_unsigned.h> +#include <__utility/declval.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__random/linear_congruential_engine.h b/lib/libcxx/include/__random/linear_congruential_engine.h index 0d91f14120..2c2276eccf 100644 --- a/lib/libcxx/include/__random/linear_congruential_engine.h +++ b/lib/libcxx/include/__random/linear_congruential_engine.h @@ -11,9 +11,11 @@ #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_unsigned.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -294,9 +296,9 @@ private: void seed(false_type, false_type, result_type __s) {__x_ = __s % __m;} template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); template diff --git a/lib/libcxx/include/__random/log2.h b/lib/libcxx/include/__random/log2.h index 72bf0759ee..4ccd1ddc9b 100644 --- a/lib/libcxx/include/__random/log2.h +++ b/lib/libcxx/include/__random/log2.h @@ -10,8 +10,8 @@ #define _LIBCPP___RANDOM_LOG2_H #include <__config> +#include <__type_traits/conditional.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/lib/libcxx/include/__random/lognormal_distribution.h b/lib/libcxx/include/__random/lognormal_distribution.h index 048d7dade9..1e8ac39dba 100644 --- a/lib/libcxx/include/__random/lognormal_distribution.h +++ b/lib/libcxx/include/__random/lognormal_distribution.h @@ -24,142 +24,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#ifdef _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - -template -class _LIBCPP_TEMPLATE_VIS lognormal_distribution -{ -public: - // types - typedef _RealType result_type; - - class _LIBCPP_TEMPLATE_VIS param_type - { - normal_distribution __nd_; - public: - typedef lognormal_distribution distribution_type; - - _LIBCPP_INLINE_VISIBILITY - explicit param_type(result_type __m = 0, result_type __s = 1) - : __nd_(__m, __s) {} - - _LIBCPP_INLINE_VISIBILITY - result_type m() const {return __nd_.mean();} - _LIBCPP_INLINE_VISIBILITY - result_type s() const {return __nd_.stddev();} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(const param_type& __x, const param_type& __y) - {return __x.__nd_ == __y.__nd_;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(const param_type& __x, const param_type& __y) - {return !(__x == __y);} - friend class lognormal_distribution; - - template - friend - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x); - - template - friend - basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x); - }; - -private: - param_type __p_; - -public: - // constructor and reset functions -#ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY - lognormal_distribution() : lognormal_distribution(0) {} - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(result_type __m, result_type __s = 1) - : __p_(param_type(__m, __s)) {} -#else - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(result_type __m = 0, - result_type __s = 1) - : __p_(param_type(__m, __s)) {} -#endif - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(const param_type& __p) - : __p_(__p) {} - _LIBCPP_INLINE_VISIBILITY - void reset() {__p_.__nd_.reset();} - - // generating functions - template - _LIBCPP_INLINE_VISIBILITY - result_type operator()(_URNG& __g) - {return (*this)(__g, __p_);} - template - _LIBCPP_INLINE_VISIBILITY - result_type operator()(_URNG& __g, const param_type& __p) - {return _VSTD::exp(const_cast&>(__p.__nd_)(__g));} - - // property functions - _LIBCPP_INLINE_VISIBILITY - result_type m() const {return __p_.m();} - _LIBCPP_INLINE_VISIBILITY - result_type s() const {return __p_.s();} - - _LIBCPP_INLINE_VISIBILITY - param_type param() const {return __p_;} - _LIBCPP_INLINE_VISIBILITY - void param(const param_type& __p) {__p_ = __p;} - - _LIBCPP_INLINE_VISIBILITY - result_type min() const {return 0;} - _LIBCPP_INLINE_VISIBILITY - result_type max() const {return numeric_limits::infinity();} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(const lognormal_distribution& __x, - const lognormal_distribution& __y) - {return __x.__p_ == __y.__p_;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(const lognormal_distribution& __x, - const lognormal_distribution& __y) - {return !(__x == __y);} - - template - friend - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x); - - template - friend - basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x); -}; - -template -inline _LIBCPP_INLINE_VISIBILITY -basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x) -{ - return __os << __x.__p_.__nd_; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -basic_istream<_CharT, _Traits>& -operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x) -{ - return __is >> __x.__p_.__nd_; -} - -#else // _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - template class _LIBCPP_TEMPLATE_VIS lognormal_distribution { @@ -290,8 +154,6 @@ operator>>(basic_istream<_CharT, _Traits>& __is, return __is >> __x.__nd_; } -#endif // _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/lib/libcxx/include/__random/mersenne_twister_engine.h b/lib/libcxx/include/__random/mersenne_twister_engine.h index 3a58e311b0..663a6c704b 100644 --- a/lib/libcxx/include/__random/mersenne_twister_engine.h +++ b/lib/libcxx/include/__random/mersenne_twister_engine.h @@ -17,7 +17,6 @@ #include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -141,7 +140,7 @@ public: explicit mersenne_twister_engine(_Sseq& __q, typename enable_if<__is_seed_sequence<_Sseq, mersenne_twister_engine>::value>::type* = 0) {seed(__q);} - void seed(result_type __sd = default_seed); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd = default_seed); template _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -153,7 +152,7 @@ public: {__seed(__q, integral_constant());} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} @@ -199,9 +198,9 @@ public: private: template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); template _LIBCPP_INLINE_VISIBILITY @@ -403,9 +402,9 @@ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, const size_t __j = (__i_ + 1) % __n; const result_type __mask = __r == _Dt ? result_type(~0) : (result_type(1) << __r) - result_type(1); - const result_type _Yp = (__x_[__i_] & ~__mask) | (__x_[__j] & __mask); + const result_type __yp = (__x_[__i_] & ~__mask) | (__x_[__j] & __mask); const size_t __k = (__i_ + __m) % __n; - __x_[__i_] = __x_[__k] ^ __rshift<1>(_Yp) ^ (__a * (_Yp & 1)); + __x_[__i_] = __x_[__k] ^ __rshift<1>(__yp) ^ (__a * (__yp & 1)); result_type __z = __x_[__i_] ^ (__rshift<__u>(__x_[__i_]) & __d); __i_ = __j; __z ^= __lshift<__s>(__z) & __b; diff --git a/lib/libcxx/include/__random/negative_binomial_distribution.h b/lib/libcxx/include/__random/negative_binomial_distribution.h index 333c9350cd..21942710fe 100644 --- a/lib/libcxx/include/__random/negative_binomial_distribution.h +++ b/lib/libcxx/include/__random/negative_binomial_distribution.h @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -135,8 +136,9 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_ else ++__f; } - _LIBCPP_ASSERT(__f >= 0, "std::negative_binomial_distribution should never produce negative values. " - "This is almost certainly a signed integer overflow issue on __f."); + _LIBCPP_ASSERT_UNCATEGORIZED(__f >= 0, + "std::negative_binomial_distribution should never produce negative values. " + "This is almost certainly a signed integer overflow issue on __f."); return __f; } return poisson_distribution(gamma_distribution diff --git a/lib/libcxx/include/__random/normal_distribution.h b/lib/libcxx/include/__random/normal_distribution.h index b2ed47e6af..e2bf041b71 100644 --- a/lib/libcxx/include/__random/normal_distribution.h +++ b/lib/libcxx/include/__random/normal_distribution.h @@ -86,7 +86,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -133,30 +134,30 @@ _RealType normal_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); - result_type _Up; + result_type __up; if (__v_hot_) { __v_hot_ = false; - _Up = __v_; + __up = __v_; } else { - uniform_real_distribution _Uni(-1, 1); + uniform_real_distribution __uni(-1, 1); result_type __u; result_type __v; result_type __s; do { - __u = _Uni(__g); - __v = _Uni(__g); + __u = __uni(__g); + __v = __uni(__g); __s = __u * __u + __v * __v; } while (__s > 1 || __s == 0); - result_type _Fp = _VSTD::sqrt(-2 * _VSTD::log(__s) / __s); - __v_ = __v * _Fp; + result_type __fp = _VSTD::sqrt(-2 * _VSTD::log(__s) / __s); + __v_ = __v * __fp; __v_hot_ = true; - _Up = __u * _Fp; + __up = __u * __fp; } - return _Up * __p.stddev() + __p.mean(); + return __up * __p.stddev() + __p.mean(); } template @@ -189,16 +190,16 @@ operator>>(basic_istream<_CharT, _Traits>& __is, __is.flags(_Istream::dec | _Istream::skipws); result_type __mean; result_type __stddev; - result_type _Vp = 0; - bool _V_hot = false; - __is >> __mean >> __stddev >> _V_hot; - if (_V_hot) - __is >> _Vp; + result_type __vp = 0; + bool __v_hot = false; + __is >> __mean >> __stddev >> __v_hot; + if (__v_hot) + __is >> __vp; if (!__is.fail()) { __x.param(param_type(__mean, __stddev)); - __x.__v_hot_ = _V_hot; - __x.__v_ = _Vp; + __x.__v_hot_ = __v_hot; + __x.__v_ = __vp; } return __is; } diff --git a/lib/libcxx/include/__random/piecewise_constant_distribution.h b/lib/libcxx/include/__random/piecewise_constant_distribution.h index a1f3ef9df5..5b26ab65e6 100644 --- a/lib/libcxx/include/__random/piecewise_constant_distribution.h +++ b/lib/libcxx/include/__random/piecewise_constant_distribution.h @@ -41,19 +41,19 @@ public: public: typedef piecewise_constant_distribution distribution_type; - param_type(); + _LIBCPP_HIDE_FROM_ABI param_type(); template - param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, + _LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w); #ifndef _LIBCPP_CXX03_LANG template - param_type(initializer_list __bl, _UnaryOperation __fw); + _LIBCPP_HIDE_FROM_ABI param_type(initializer_list __bl, _UnaryOperation __fw); #endif // _LIBCPP_CXX03_LANG template - param_type(size_t __nw, result_type __xmin, result_type __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw); - param_type(param_type const&) = default; - param_type & operator=(const param_type& __rhs); + _LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default; + _LIBCPP_HIDE_FROM_ABI param_type & operator=(const param_type& __rhs); _LIBCPP_INLINE_VISIBILITY vector intervals() const {return __b_;} @@ -68,7 +68,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class piecewise_constant_distribution; @@ -125,7 +125,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/piecewise_linear_distribution.h b/lib/libcxx/include/__random/piecewise_linear_distribution.h index fc2eb47c7b..6be44b29fc 100644 --- a/lib/libcxx/include/__random/piecewise_linear_distribution.h +++ b/lib/libcxx/include/__random/piecewise_linear_distribution.h @@ -41,19 +41,19 @@ public: public: typedef piecewise_linear_distribution distribution_type; - param_type(); + _LIBCPP_HIDE_FROM_ABI param_type(); template - param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, + _LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w); #ifndef _LIBCPP_CXX03_LANG template - param_type(initializer_list __bl, _UnaryOperation __fw); + _LIBCPP_HIDE_FROM_ABI param_type(initializer_list __bl, _UnaryOperation __fw); #endif // _LIBCPP_CXX03_LANG template - param_type(size_t __nw, result_type __xmin, result_type __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw); - param_type(param_type const&) = default; - param_type & operator=(const param_type& __rhs); + _LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default; + _LIBCPP_HIDE_FROM_ABI param_type & operator=(const param_type& __rhs); _LIBCPP_INLINE_VISIBILITY vector intervals() const {return __b_;} @@ -68,7 +68,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class piecewise_linear_distribution; @@ -125,7 +125,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -188,23 +189,23 @@ void piecewise_linear_distribution<_RealType>::param_type::__init() { __areas_.assign(__densities_.size() - 1, result_type()); - result_type _Sp = 0; + result_type __sp = 0; for (size_t __i = 0; __i < __areas_.size(); ++__i) { __areas_[__i] = (__densities_[__i+1] + __densities_[__i]) * (__b_[__i+1] - __b_[__i]) * .5; - _Sp += __areas_[__i]; + __sp += __areas_[__i]; } for (size_t __i = __areas_.size(); __i > 1;) { --__i; - __areas_[__i] = __areas_[__i-1] / _Sp; + __areas_[__i] = __areas_[__i-1] / __sp; } __areas_[0] = 0; for (size_t __i = 1; __i < __areas_.size(); ++__i) __areas_[__i] += __areas_[__i-1]; for (size_t __i = 0; __i < __densities_.size(); ++__i) - __densities_[__i] /= _Sp; + __densities_[__i] /= __sp; } template diff --git a/lib/libcxx/include/__random/poisson_distribution.h b/lib/libcxx/include/__random/poisson_distribution.h index 334c6102b3..eed120ebb7 100644 --- a/lib/libcxx/include/__random/poisson_distribution.h +++ b/lib/libcxx/include/__random/poisson_distribution.h @@ -52,7 +52,7 @@ public: public: typedef poisson_distribution distribution_type; - explicit param_type(double __mean = 1.0); + _LIBCPP_HIDE_FROM_ABI explicit param_type(double __mean = 1.0); _LIBCPP_INLINE_VISIBILITY double mean() const {return __mean_;} @@ -93,7 +93,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -144,12 +145,12 @@ poisson_distribution<_IntType>::param_type::param_type(double __mean) __d_ = 6 * __mean_ * __mean_; __l_ = _VSTD::trunc(__mean_ - 1.1484); __omega_ = .3989423 / __s_; - double __b1_ = .4166667E-1 / __mean_; - double __b2_ = .3 * __b1_ * __b1_; - __c3_ = .1428571 * __b1_ * __b2_; - __c2_ = __b2_ - 15. * __c3_; - __c1_ = __b1_ - 6. * __b2_ + 45. * __c3_; - __c0_ = 1. - __b1_ + 3. * __b2_ - 15. * __c3_; + double __b1 = .4166667E-1 / __mean_; + double __b2 = .3 * __b1 * __b1; + __c3_ = .1428571 * __b1 * __b2; + __c2_ = __b2 - 15. * __c3_; + __c1_ = __b1 - 6. * __b2 + 45. * __c3_; + __c0_ = 1. - __b1 + 3. * __b2 - 15. * __c3_; __c_ = .1069 / __mean_; } } diff --git a/lib/libcxx/include/__random/random_device.h b/lib/libcxx/include/__random/random_device.h index e82b437a3b..e7c37241a7 100644 --- a/lib/libcxx/include/__random/random_device.h +++ b/lib/libcxx/include/__random/random_device.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) -class _LIBCPP_TYPE_VIS random_device +class _LIBCPP_EXPORTED_FROM_ABI random_device { #ifdef _LIBCPP_USING_DEV_RANDOM int __f_; @@ -58,7 +58,7 @@ public: // constructors #ifndef _LIBCPP_CXX03_LANG - random_device() : random_device("/dev/urandom") {} + _LIBCPP_HIDE_FROM_ABI random_device() : random_device("/dev/urandom") {} explicit random_device(const string& __token); #else explicit random_device(const string& __token = "/dev/urandom"); diff --git a/lib/libcxx/include/__random/seed_seq.h b/lib/libcxx/include/__random/seed_seq.h index 330537fa00..506b979cf8 100644 --- a/lib/libcxx/include/__random/seed_seq.h +++ b/lib/libcxx/include/__random/seed_seq.h @@ -13,6 +13,8 @@ #include <__algorithm/fill.h> #include <__algorithm/max.h> #include <__config> +#include <__iterator/iterator_traits.h> +#include #include #include @@ -52,7 +54,7 @@ public: // generating functions template - void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); + _LIBCPP_HIDE_FROM_ABI void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); // property functions _LIBCPP_INLINE_VISIBILITY @@ -70,7 +72,7 @@ public: private: template - void __init(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __init(_InputIterator __first, _InputIterator __last); vector __v_; }; diff --git a/lib/libcxx/include/__random/shuffle_order_engine.h b/lib/libcxx/include/__random/shuffle_order_engine.h index 4a27289c2f..e07f230d21 100644 --- a/lib/libcxx/include/__random/shuffle_order_engine.h +++ b/lib/libcxx/include/__random/shuffle_order_engine.h @@ -12,10 +12,13 @@ #include <__algorithm/equal.h> #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -201,10 +204,10 @@ private: _LIBCPP_INLINE_VISIBILITY result_type __evalf() { - const double _Fp = __d == 0 ? + const double __fp = __d == 0 ? __n / (2. * 0x8000000000000000ull) : __n / (double)__d; - const size_t __j = static_cast(_Fp * (__y_ - _Min)); + const size_t __j = static_cast(__fp * (__y_ - _Min)); __y_ = __v_[__j]; __v_[__j] = __e_(); return __y_; @@ -262,16 +265,16 @@ operator>>(basic_istream<_CharT, _Traits>& __is, typedef basic_istream<_CharT, _Traits> _Istream; __is.flags(_Istream::dec | _Istream::skipws); _Eng __e; - result_type _Vp[_Kp+1]; + result_type __vp[_Kp+1]; __is >> __e; for (size_t __i = 0; __i < _Kp+1; ++__i) - __is >> _Vp[__i]; + __is >> __vp[__i]; if (!__is.fail()) { __x.__e_ = __e; for (size_t __i = 0; __i < _Kp; ++__i) - __x.__v_[__i] = _Vp[__i]; - __x.__y_ = _Vp[_Kp]; + __x.__v_[__i] = __vp[__i]; + __x.__y_ = __vp[_Kp]; } return __is; } diff --git a/lib/libcxx/include/__random/student_t_distribution.h b/lib/libcxx/include/__random/student_t_distribution.h index 64847aa66a..2d2be23657 100644 --- a/lib/libcxx/include/__random/student_t_distribution.h +++ b/lib/libcxx/include/__random/student_t_distribution.h @@ -81,7 +81,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__random/subtract_with_carry_engine.h b/lib/libcxx/include/__random/subtract_with_carry_engine.h index b25ca84e3a..c8954ca111 100644 --- a/lib/libcxx/include/__random/subtract_with_carry_engine.h +++ b/lib/libcxx/include/__random/subtract_with_carry_engine.h @@ -18,7 +18,6 @@ #include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -121,7 +120,7 @@ public: {__seed(__q, integral_constant());} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} @@ -155,12 +154,12 @@ public: private: - void seed(result_type __sd, integral_constant); - void seed(result_type __sd, integral_constant); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant); template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); template - void __seed(_Sseq& __q, integral_constant); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); }; template diff --git a/lib/libcxx/include/__random/uniform_int_distribution.h b/lib/libcxx/include/__random/uniform_int_distribution.h index b7db8a3f9c..3a2b95c035 100644 --- a/lib/libcxx/include/__random/uniform_int_distribution.h +++ b/lib/libcxx/include/__random/uniform_int_distribution.h @@ -9,15 +9,16 @@ #ifndef _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H #define _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H +#include <__bit/countl.h> #include <__config> #include <__random/is_valid.h> #include <__random/log2.h> -#include +#include <__type_traits/conditional.h> +#include <__type_traits/make_unsigned.h> #include #include #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -63,14 +64,14 @@ private: public: // constructors and seeding functions - __independent_bits_engine(_Engine& __e, size_t __w); + _LIBCPP_HIDE_FROM_ABI __independent_bits_engine(_Engine& __e, size_t __w); // generating functions - result_type operator()() {return __eval(integral_constant());} + _LIBCPP_HIDE_FROM_ABI result_type operator()() {return __eval(integral_constant());} private: - result_type __eval(false_type); - result_type __eval(true_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(false_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type); }; template @@ -120,8 +121,8 @@ template _UIntType __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { - const size_t _WRt = numeric_limits::digits; - result_type _Sp = 0; + const size_t __w_rt = numeric_limits::digits; + result_type __sp = 0; for (size_t __k = 0; __k < __n0_; ++__k) { _Engine_result_type __u; @@ -129,11 +130,11 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y0_); - if (__w0_ < _WRt) - _Sp <<= __w0_; + if (__w0_ < __w_rt) + __sp <<= __w0_; else - _Sp = 0; - _Sp += __u & __mask0_; + __sp = 0; + __sp += __u & __mask0_; } for (size_t __k = __n0_; __k < __n_; ++__k) { @@ -142,13 +143,13 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y1_); - if (__w0_ < _WRt - 1) - _Sp <<= __w0_ + 1; + if (__w0_ < __w_rt - 1) + __sp <<= __w0_ + 1; else - _Sp = 0; - _Sp += __u & __mask1_; + __sp = 0; + __sp += __u & __mask1_; } - return _Sp; + return __sp; } template @@ -166,12 +167,12 @@ public: public: typedef uniform_int_distribution distribution_type; - explicit param_type(result_type __a = 0, + _LIBCPP_HIDE_FROM_ABI explicit param_type(result_type __a = 0, result_type __b = numeric_limits::max()) : __a_(__a), __b_(__b) {} - result_type a() const {return __a_;} - result_type b() const {return __b_;} + _LIBCPP_HIDE_FROM_ABI result_type a() const {return __a_;} + _LIBCPP_HIDE_FROM_ABI result_type b() const {return __b_;} _LIBCPP_HIDE_FROM_ABI friend bool operator==(const param_type& __x, const param_type& __y) @@ -187,8 +188,8 @@ private: public: // constructors and reset functions #ifndef _LIBCPP_CXX03_LANG - uniform_int_distribution() : uniform_int_distribution(0) {} - explicit uniform_int_distribution( + _LIBCPP_HIDE_FROM_ABI uniform_int_distribution() : uniform_int_distribution(0) {} + _LIBCPP_HIDE_FROM_ABI explicit uniform_int_distribution( result_type __a, result_type __b = numeric_limits::max()) : __p_(param_type(__a, __b)) {} #else @@ -197,23 +198,25 @@ public: result_type __b = numeric_limits::max()) : __p_(param_type(__a, __b)) {} #endif - explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} - void reset() {} + _LIBCPP_HIDE_FROM_ABI explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} + _LIBCPP_HIDE_FROM_ABI void reset() {} // generating functions - template result_type operator()(_URNG& __g) + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template result_type operator()(_URNG& __g, const param_type& __p); + template + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions - result_type a() const {return __p_.a();} - result_type b() const {return __p_.b();} + _LIBCPP_HIDE_FROM_ABI result_type a() const {return __p_.a();} + _LIBCPP_HIDE_FROM_ABI result_type b() const {return __p_.b();} - param_type param() const {return __p_;} - void param(const param_type& __p) {__p_ = __p;} + _LIBCPP_HIDE_FROM_ABI param_type param() const {return __p_;} + _LIBCPP_HIDE_FROM_ABI void param(const param_type& __p) {__p_ = __p;} - result_type min() const {return a();} - result_type max() const {return b();} + _LIBCPP_HIDE_FROM_ABI result_type min() const {return a();} + _LIBCPP_HIDE_FROM_ABI result_type max() const {return b();} _LIBCPP_HIDE_FROM_ABI friend bool operator==(const uniform_int_distribution& __x, @@ -234,22 +237,22 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); typedef __conditional_t > _UIntType; - const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); - if (_Rp == 1) + const _UIntType __rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); + if (__rp == 1) return __p.a(); - const size_t _Dt = numeric_limits<_UIntType>::digits; + const size_t __dt = numeric_limits<_UIntType>::digits; typedef __independent_bits_engine<_URNG, _UIntType> _Eng; - if (_Rp == 0) - return static_cast(_Eng(__g, _Dt)()); - size_t __w = _Dt - std::__countl_zero(_Rp) - 1; - if ((_Rp & (numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0) + if (__rp == 0) + return static_cast(_Eng(__g, __dt)()); + size_t __w = __dt - std::__countl_zero(__rp) - 1; + if ((__rp & (numeric_limits<_UIntType>::max() >> (__dt - __w))) != 0) ++__w; _Eng __e(__g, __w); _UIntType __u; do { __u = __e(); - } while (__u >= _Rp); + } while (__u >= __rp); return static_cast(__u + __p.a()); } diff --git a/lib/libcxx/include/__random/uniform_random_bit_generator.h b/lib/libcxx/include/__random/uniform_random_bit_generator.h index 84a30b0ebe..ddb3158eea 100644 --- a/lib/libcxx/include/__random/uniform_random_bit_generator.h +++ b/lib/libcxx/include/__random/uniform_random_bit_generator.h @@ -13,7 +13,8 @@ #include <__concepts/invocable.h> #include <__concepts/same_as.h> #include <__config> -#include +#include <__functional/invoke.h> +#include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +25,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [rand.req.urng] template @@ -36,7 +37,7 @@ concept uniform_random_bit_generator = requires bool_constant<(_Gen::min() < _Gen::max())>::value; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__random/uniform_real_distribution.h b/lib/libcxx/include/__random/uniform_real_distribution.h index b52b68977f..1388cef95f 100644 --- a/lib/libcxx/include/__random/uniform_real_distribution.h +++ b/lib/libcxx/include/__random/uniform_real_distribution.h @@ -14,7 +14,6 @@ #include <__random/is_valid.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -65,7 +64,7 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY uniform_real_distribution() : uniform_real_distribution(0) {} - explicit uniform_real_distribution(result_type __a, result_type __b = 1) + _LIBCPP_HIDE_FROM_ABI explicit uniform_real_distribution(result_type __a, result_type __b = 1) : __p_(param_type(__a, __b)) {} #else _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/__ranges/access.h b/lib/libcxx/include/__ranges/access.h index e48a71adf7..502bd5e951 100644 --- a/lib/libcxx/include/__ranges/access.h +++ b/lib/libcxx/include/__ranges/access.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -223,7 +223,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/all.h b/lib/libcxx/include/__ranges/all.h index 511f7b3b46..2c88f51b66 100644 --- a/lib/libcxx/include/__ranges/all.h +++ b/lib/libcxx/include/__ranges/all.h @@ -11,6 +11,8 @@ #define _LIBCPP___RANGES_ALL_H #include <__config> +#include <__functional/compose.h> // TODO(modules): Those should not be required +#include <__functional/perfect_forward.h> // #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> @@ -18,10 +20,10 @@ #include <__ranges/owning_view.h> #include <__ranges/range_adaptor.h> #include <__ranges/ref_view.h> +#include <__type_traits/decay.h> #include <__utility/auto_cast.h> #include <__utility/declval.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -29,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges::views { @@ -77,7 +79,7 @@ using all_t = decltype(views::all(std::declval<_Range>())); } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/as_rvalue_view.h b/lib/libcxx/include/__ranges/as_rvalue_view.h index 422d8a8e08..295aa94ed9 100644 --- a/lib/libcxx/include/__ranges/as_rvalue_view.h +++ b/lib/libcxx/include/__ranges/as_rvalue_view.h @@ -28,6 +28,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD @@ -125,7 +128,7 @@ struct __fn : __range_adaptor_closure<__fn> { } // namespace __as_rvalue inline namespace __cpo { -constexpr auto as_rvalue = __as_rvalue::__fn{}; +inline constexpr auto as_rvalue = __as_rvalue::__fn{}; } // namespace __cpo } // namespace views } // namespace ranges @@ -134,4 +137,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_AS_RVALUE_H diff --git a/lib/libcxx/include/__ranges/common_view.h b/lib/libcxx/include/__ranges/common_view.h index 8d7ae58415..f4cd180749 100644 --- a/lib/libcxx/include/__ranges/common_view.h +++ b/lib/libcxx/include/__ranges/common_view.h @@ -24,15 +24,17 @@ #include <__ranges/view_interface.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #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 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -130,8 +132,10 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_COMMON_VIEW_H diff --git a/lib/libcxx/include/__ranges/concepts.h b/lib/libcxx/include/__ranges/concepts.h index e34c545578..b87a714606 100644 --- a/lib/libcxx/include/__ranges/concepts.h +++ b/lib/libcxx/include/__ranges/concepts.h @@ -37,7 +37,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -73,6 +73,9 @@ namespace ranges { template using range_rvalue_reference_t = iter_rvalue_reference_t>; + template + using range_common_reference_t = iter_common_reference_t>; + // [range.sized] template concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; @@ -140,7 +143,7 @@ namespace ranges { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/container_compatible_range.h b/lib/libcxx/include/__ranges/container_compatible_range.h new file mode 100644 index 0000000000..a58f111988 --- /dev/null +++ b/lib/libcxx/include/__ranges/container_compatible_range.h @@ -0,0 +1,33 @@ +// -*- 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___RANGES_CONTAINER_COMPATIBLE_RANGE_H +#define _LIBCPP___RANGES_CONTAINER_COMPATIBLE_RANGE_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__ranges/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template +concept _ContainerCompatibleRange = + ranges::input_range<_Range> && convertible_to, _Tp>; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_CONTAINER_COMPATIBLE_RANGE_H diff --git a/lib/libcxx/include/__ranges/copyable_box.h b/lib/libcxx/include/__ranges/copyable_box.h deleted file mode 100644 index fb3d6e409c..0000000000 --- a/lib/libcxx/include/__ranges/copyable_box.h +++ /dev/null @@ -1,180 +0,0 @@ -// -*- 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___RANGES_COPYABLE_BOX_H -#define _LIBCPP___RANGES_COPYABLE_BOX_H - -#include <__concepts/constructible.h> -#include <__concepts/copyable.h> -#include <__concepts/movable.h> -#include <__config> -#include <__memory/addressof.h> -#include <__memory/construct_at.h> -#include <__utility/move.h> -#include -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER > 17 - -// __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into -// a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state -// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary -// to handle the case where the copy construction fails after destroying the object. -// -// In some cases, we can completely avoid the use of an empty state; we provide a specialization of -// __copyable_box that does this, see below for the details. - -template -concept __copy_constructible_object = copy_constructible<_Tp> && is_object_v<_Tp>; - -namespace ranges { - // Primary template - uses std::optional and introduces an empty state in case assignment fails. - template<__copy_constructible_object _Tp> - class __copyable_box { - _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; - - public: - template - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(in_place, std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_(in_place) - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) - noexcept(is_nothrow_copy_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(*__other); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) - noexcept(is_nothrow_move_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(std::move(*__other)); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return __val_.operator->(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return __val_.operator->(); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } - }; - - // This partial specialization implements an optimization for when we know we don't need to store - // an empty state to represent failure to perform an assignment. For copy-assignment, this happens: - // - // 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator - // directly and avoid using std::optional. - // 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as - // destroy-and-then-construct and we know it will never fail, so we don't need an empty state. - // - // The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and - // nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled - // whenever we can apply any of these optimizations for both the copy assignment and the move assignment - // operator. - template - concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; - - template - concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; - - template<__copy_constructible_object _Tp> - requires __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp> - class __copyable_box<_Tp> { - _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; - - public: - template - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_() - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - // Implementation of assignment operators in case we perform optimization (1) - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box const&) requires copyable<_Tp> = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - // Implementation of assignment operators in case we perform optimization (2) - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) noexcept { - static_assert(is_nothrow_copy_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), __other.__val_); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) noexcept { - static_assert(is_nothrow_move_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), std::move(__other.__val_)); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return std::addressof(__val_); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return std::addressof(__val_); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } - }; -} // namespace ranges - -#endif // _LIBCPP_STD_VER > 17 - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___RANGES_COPYABLE_BOX_H diff --git a/lib/libcxx/include/__ranges/counted.h b/lib/libcxx/include/__ranges/counted.h index 138aa0e1dd..882f90b1ed 100644 --- a/lib/libcxx/include/__ranges/counted.h +++ b/lib/libcxx/include/__ranges/counted.h @@ -19,10 +19,11 @@ #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include <__ranges/subrange.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/move.h> +#include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges::views { @@ -75,7 +76,7 @@ inline namespace __cpo { } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/dangling.h b/lib/libcxx/include/__ranges/dangling.h index c10453454d..613084d5fb 100644 --- a/lib/libcxx/include/__ranges/dangling.h +++ b/lib/libcxx/include/__ranges/dangling.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { struct dangling { @@ -35,7 +35,7 @@ using borrowed_iterator_t = _If, iterator_t<_Rp>, dangling>; // borrowed_subrange_t defined in <__ranges/subrange.h> } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/data.h b/lib/libcxx/include/__ranges/data.h index 0ac25b52c7..6c099085af 100644 --- a/lib/libcxx/include/__ranges/data.h +++ b/lib/libcxx/include/__ranges/data.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.prim.data] @@ -105,7 +105,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/drop_view.h b/lib/libcxx/include/__ranges/drop_view.h index 8f3564a8c7..f10476f001 100644 --- a/lib/libcxx/include/__ranges/drop_view.h +++ b/lib/libcxx/include/__ranges/drop_view.h @@ -30,13 +30,19 @@ #include <__ranges/iota_view.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -47,7 +53,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -66,14 +72,14 @@ namespace ranges { _View __base_ = _View(); public: - drop_view() requires default_initializable<_View> = default; + _LIBCPP_HIDE_FROM_ABI drop_view() requires default_initializable<_View> = default; _LIBCPP_HIDE_FROM_ABI - constexpr drop_view(_View __base, range_difference_t<_View> __count) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_view(_View __base, range_difference_t<_View> __count) : __count_(__count) , __base_(std::move(__base)) { - _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ >= 0, "count must be greater than or equal to zero."); } _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } @@ -255,13 +261,39 @@ struct __fn { { // Introducing local variables avoids calculating `min` and `distance` twice (at the cost of diverging from the // expression used in the `noexcept` clause and the return statement). - auto dist = ranges::distance(__rng); - auto clamped = std::min<_Dist>(dist, std::forward<_Np>(__n)); + auto __dist = ranges::distance(__rng); + auto __clamped = std::min<_Dist>(__dist, std::forward<_Np>(__n)); return _RawRange( - ranges::begin(__rng) + clamped, + ranges::begin(__rng) + __clamped, ranges::end(__rng), - std::__to_unsigned_like(dist - clamped) + std::__to_unsigned_like(__dist - __clamped) );} +// clang-format off +#if _LIBCPP_STD_VER >= 23 + // [range.drop.overview]: the `repeat_view` "_RawRange models sized_range" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype( views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) + { return views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } + + // [range.drop.overview]: the `repeat_view` "otherwise" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Np&&) const + noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) + -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) + { return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); } +#endif +// clang-format on // [range.drop.overview]: the "otherwise" case. template > _Np, @@ -269,6 +301,9 @@ struct __fn { // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. requires (!(__is_empty_view<_RawRange> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || @@ -299,7 +334,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/drop_while_view.h b/lib/libcxx/include/__ranges/drop_while_view.h index 7c28992f18..677b5bc66d 100644 --- a/lib/libcxx/include/__ranges/drop_while_view.h +++ b/lib/libcxx/include/__ranges/drop_while_view.h @@ -20,8 +20,8 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -51,7 +51,7 @@ public: requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI constexpr drop_while_view(_View __base, _Pred __pred) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_while_view(_View __base, _Pred __pred) : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& @@ -65,9 +65,10 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; } _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { - _LIBCPP_ASSERT(__pred_.__has_value(), - "drop_while_view needs to have a non-empty predicate before calling begin() -- did a previous " - "assignment to this drop_while_view fail?"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __pred_.__has_value(), + "drop_while_view needs to have a non-empty predicate before calling begin() -- did a previous " + "assignment to this drop_while_view fail?"); if constexpr (_UseCache) { if (!__cached_begin_.__has_value()) { __cached_begin_.__emplace(ranges::find_if_not(__base_, std::cref(*__pred_))); @@ -82,7 +83,7 @@ public: private: _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; static constexpr bool _UseCache = forward_range<_View>; using _Cache = _If<_UseCache, __non_propagating_cache>, __empty_cache>; diff --git a/lib/libcxx/include/__ranges/elements_view.h b/lib/libcxx/include/__ranges/elements_view.h index 997380ee9c..325e4c9dca 100644 --- a/lib/libcxx/include/__ranges/elements_view.h +++ b/lib/libcxx/include/__ranges/elements_view.h @@ -26,9 +26,9 @@ #include <__ranges/range_adaptor.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_like.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_like.h> +#include <__tuple/tuple_size.h> #include <__type_traits/is_reference.h> #include <__type_traits/maybe_const.h> #include <__type_traits/remove_cv.h> @@ -224,9 +224,9 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) requires forward_range<_Base> { - auto temp = *this; + auto __temp = *this; ++__current_; - return temp; + return __temp; } _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() @@ -239,9 +239,9 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) requires bidirectional_range<_Base> { - auto temp = *this; + auto __temp = *this; --__current_; - return temp; + return __temp; } _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) diff --git a/lib/libcxx/include/__ranges/empty.h b/lib/libcxx/include/__ranges/empty.h index 8a1c75c0ba..64996f4a6f 100644 --- a/lib/libcxx/include/__ranges/empty.h +++ b/lib/libcxx/include/__ranges/empty.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.prim.empty] @@ -75,7 +75,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/empty_view.h b/lib/libcxx/include/__ranges/empty_view.h index 58e69ac19f..bb445b4e6f 100644 --- a/lib/libcxx/include/__ranges/empty_view.h +++ b/lib/libcxx/include/__ranges/empty_view.h @@ -13,7 +13,8 @@ #include <__config> #include <__ranges/enable_borrowed_range.h> #include <__ranges/view_interface.h> -#include +#include <__type_traits/is_object.h> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -46,7 +47,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/enable_borrowed_range.h b/lib/libcxx/include/__ranges/enable_borrowed_range.h index 833d266403..1d068335e2 100644 --- a/lib/libcxx/include/__ranges/enable_borrowed_range.h +++ b/lib/libcxx/include/__ranges/enable_borrowed_range.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -33,7 +33,7 @@ inline constexpr bool enable_borrowed_range = false; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/enable_view.h b/lib/libcxx/include/__ranges/enable_view.h index c85064b915..0c1dff3821 100644 --- a/lib/libcxx/include/__ranges/enable_view.h +++ b/lib/libcxx/include/__ranges/enable_view.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -43,7 +43,7 @@ inline constexpr bool enable_view = derived_from<_Tp, view_base> || } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/filter_view.h b/lib/libcxx/include/__ranges/filter_view.h index e14a9abeb9..1cef94ca67 100644 --- a/lib/libcxx/include/__ranges/filter_view.h +++ b/lib/libcxx/include/__ranges/filter_view.h @@ -11,12 +11,12 @@ #define _LIBCPP___RANGES_FILTER_VIEW_H #include <__algorithm/ranges_find_if.h> +#include <__assert> #include <__concepts/constructible.h> #include <__concepts/copyable.h> #include <__concepts/derived_from.h> #include <__concepts/equality_comparable.h> #include <__config> -#include <__debug> #include <__functional/bind_back.h> #include <__functional/invoke.h> #include <__functional/reference_wrapper.h> @@ -28,14 +28,17 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,14 +46,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template> _Pred> requires view<_View> && is_object_v<_Pred> class filter_view : public view_interface> { _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; // We cache the result of begin() to allow providing an amortized O(1) begin() whenever // the underlying range is at least a forward_range. @@ -65,10 +68,8 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI filter_view() requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI - constexpr filter_view(_View __base, _Pred __pred) - : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) - { } + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 filter_view(_View __base, _Pred __pred) + : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) {} template _LIBCPP_HIDE_FROM_ABI @@ -81,7 +82,9 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { - _LIBCPP_ASSERT(__pred_.__has_value(), "Trying to call begin() on a filter_view that does not have a valid predicate."); + _LIBCPP_ASSERT_UNCATEGORIZED( + __pred_.__has_value(), + "Trying to call begin() on a filter_view that does not have a valid predicate."); if constexpr (_UseCache) { if (!__cached_begin_.__has_value()) { __cached_begin_.__emplace(ranges::find_if(__base_, std::ref(*__pred_))); @@ -180,9 +183,9 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) requires bidirectional_range<_View> { - auto tmp = *this; + auto __tmp = *this; --*this; - return tmp; + return __tmp; } _LIBCPP_HIDE_FROM_ABI @@ -257,7 +260,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/from_range.h b/lib/libcxx/include/__ranges/from_range.h new file mode 100644 index 0000000000..a6cb9e3d43 --- /dev/null +++ b/lib/libcxx/include/__ranges/from_range.h @@ -0,0 +1,33 @@ +// -*- 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___RANGES_FROM_RANGE_H +#define _LIBCPP___RANGES_FROM_RANGE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +struct from_range_t { + explicit from_range_t() = default; +}; + +inline constexpr from_range_t from_range{}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_FROM_RANGE_H diff --git a/lib/libcxx/include/__ranges/iota_view.h b/lib/libcxx/include/__ranges/iota_view.h index 8f9148a684..f372688abf 100644 --- a/lib/libcxx/include/__ranges/iota_view.h +++ b/lib/libcxx/include/__ranges/iota_view.h @@ -27,12 +27,15 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/unreachable_sentinel.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -40,12 +43,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template struct __get_wider_signed { - static auto __call() { + consteval static auto __call() { if constexpr (sizeof(_Int) < sizeof(short)) return type_identity{}; else if constexpr (sizeof(_Int) < sizeof(int)) return type_identity{}; else if constexpr (sizeof(_Int) < sizeof(long)) return type_identity{}; @@ -278,7 +281,8 @@ namespace ranges { public: _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) + : __bound_sentinel_(std::move(__bound_sentinel)) {} _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { @@ -311,28 +315,28 @@ namespace ranges { constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) { } _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel) : __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) { // Validate the precondition if possible. if constexpr (totally_ordered_with<_Start, _BoundSentinel>) { - _LIBCPP_ASSERT(ranges::less_equal()(__value_, __bound_sentinel_), - "Precondition violated: value is greater than bound."); + _LIBCPP_ASSERT_UNCATEGORIZED(ranges::less_equal()(__value_, __bound_sentinel_), + "Precondition violated: value is greater than bound."); } } _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, __iterator __last) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last) requires same_as<_Start, _BoundSentinel> : iota_view(std::move(__first.__value_), std::move(__last.__value_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, _BoundSentinel __last) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last) requires same_as<_BoundSentinel, unreachable_sentinel_t> : iota_view(std::move(__first.__value_), std::move(__last)) {} _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, __sentinel __last) - requires(!same_as<_Start, _BoundSentinel> && !same_as<_Start, unreachable_sentinel_t>) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last) + requires(!same_as<_Start, _BoundSentinel> && !same_as<_BoundSentinel, unreachable_sentinel_t>) : iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {} _LIBCPP_HIDE_FROM_ABI @@ -403,7 +407,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/join_view.h b/lib/libcxx/include/__ranges/join_view.h index 7c078422e9..e6240dfd25 100644 --- a/lib/libcxx/include/__ranges/join_view.h +++ b/lib/libcxx/include/__ranges/join_view.h @@ -22,6 +22,7 @@ #include <__iterator/iterator_traits.h> #include <__iterator/iterator_with_data.h> #include <__iterator/segmented_iterator.h> +#include <__memory/addressof.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> @@ -29,10 +30,10 @@ #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/common_type.h> #include <__type_traits/maybe_const.h> #include <__utility/forward.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Note: `join_view` is still marked experimental because there is an ABI-breaking change that affects `join_view` in // the pipeline (https://isocpp.org/files/papers/D2770R0.html). // TODO: make `join_view` non-experimental once D2770 is implemented. -#if _LIBCPP_STD_VER > 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) namespace ranges { template @@ -394,8 +395,8 @@ inline namespace __cpo { template requires(_JoinViewIterator::__is_join_view_iterator && ranges::common_range && - __is_cpp17_random_access_iterator::value && - __is_cpp17_random_access_iterator::value) + __has_random_access_iterator_category::value && + __has_random_access_iterator_category::value) struct __segmented_iterator_traits<_JoinViewIterator> { using __segment_iterator = @@ -435,7 +436,7 @@ struct __segmented_iterator_traits<_JoinViewIterator> { } }; -#endif // #if _LIBCPP_STD_VER > 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // #if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/lazy_split_view.h b/lib/libcxx/include/__ranges/lazy_split_view.h index 3a95075884..04182a530f 100644 --- a/lib/libcxx/include/__ranges/lazy_split_view.h +++ b/lib/libcxx/include/__ranges/lazy_split_view.h @@ -12,6 +12,7 @@ #include <__algorithm/ranges_find.h> #include <__algorithm/ranges_mismatch.h> +#include <__assert> #include <__concepts/constructible.h> #include <__concepts/convertible_to.h> #include <__concepts/derived_from.h> @@ -34,10 +35,13 @@ #include <__ranges/single_view.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -45,7 +49,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -78,14 +82,14 @@ public: requires default_initializable<_View> && default_initializable<_Pattern> = default; _LIBCPP_HIDE_FROM_ABI - constexpr lazy_split_view(_View __base, _Pattern __pattern) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_View __base, _Pattern __pattern) : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {} template requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view>> _LIBCPP_HIDE_FROM_ABI - constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_Range&& __r, range_value_t<_Range> __e) : __base_(views::all(std::forward<_Range>(__r))) , __pattern_(views::single(std::move(__e))) {} @@ -276,7 +280,7 @@ private: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) { - _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); + _LIBCPP_ASSERT_UNCATEGORIZED(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; } }; @@ -307,7 +311,7 @@ private: _LIBCPP_HIDE_FROM_ABI constexpr bool __is_done() const { - _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); + _LIBCPP_ASSERT_UNCATEGORIZED(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; auto __end = ranges::end(__i_.__parent_->__base_); @@ -458,7 +462,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/movable_box.h b/lib/libcxx/include/__ranges/movable_box.h new file mode 100644 index 0000000000..8b3716a06c --- /dev/null +++ b/lib/libcxx/include/__ranges/movable_box.h @@ -0,0 +1,206 @@ +// -*- 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___RANGES_MOVABLE_BOX_H +#define _LIBCPP___RANGES_MOVABLE_BOX_H + +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/movable.h> +#include <__config> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// __movable_box allows turning a type that is move-constructible (but maybe not move-assignable) into +// a type that is both move-constructible and move-assignable. It does that by introducing an empty state +// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary +// to handle the case where the copy construction fails after destroying the object. +// +// In some cases, we can completely avoid the use of an empty state; we provide a specialization of +// __movable_box that does this, see below for the details. + +// until C++23, `__movable_box` was named `__copyable_box` and required the stored type to be copy-constructible, not +// just move-constructible; we preserve the old behavior in pre-C++23 modes. +template +concept __movable_box_object = +# if _LIBCPP_STD_VER >= 23 + move_constructible<_Tp> +# else + copy_constructible<_Tp> +# endif + && is_object_v<_Tp>; + +namespace ranges { +// Primary template - uses std::optional and introduces an empty state in case assignment fails. +template <__movable_box_object _Tp> +class __movable_box { + _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; + +public: + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(in_place, std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_(in_place) {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box const& __other) noexcept(is_nothrow_copy_constructible_v<_Tp>) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(*__other); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(std::move(*__other)); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return __val_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return __val_.operator->(); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } +}; + +// This partial specialization implements an optimization for when we know we don't need to store +// an empty state to represent failure to perform an assignment. For copy-assignment, this happens: +// +// 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator +// directly and avoid using std::optional. +// 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as +// destroy-and-then-construct and we know it will never fail, so we don't need an empty state. +// +// The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and +// nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled +// whenever we can apply any of these optimizations for both the copy assignment and the move assignment +// operator. + +# if _LIBCPP_STD_VER >= 23 +template +concept __doesnt_need_empty_state = + (copy_constructible<_Tp> + // 1. If copy_constructible is true, movable-box should store only a T if either T models + // copyable, or is_nothrow_move_constructible_v && is_nothrow_copy_constructible_v is true. + ? copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>) + // 2. Otherwise, movable-box should store only a T if either T models movable or + // is_nothrow_move_constructible_v is true. + : movable<_Tp> || is_nothrow_move_constructible_v<_Tp>); +# else + +template +concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; + +template +concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; + +template +concept __doesnt_need_empty_state = __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp>; +# endif + +template <__movable_box_object _Tp> + requires __doesnt_need_empty_state<_Tp> +class __movable_box<_Tp> { + _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; + +public: + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_() {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + // Implementation of assignment operators in case we perform optimization (1) + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box const&) + requires copyable<_Tp> + = default; + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + // Implementation of assignment operators in case we perform optimization (2) + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box const& __other) noexcept { + static_assert(is_nothrow_copy_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), __other.__val_); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box&& __other) noexcept { + static_assert(is_nothrow_move_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), std::move(__other.__val_)); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return std::addressof(__val_); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return std::addressof(__val_); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } +}; +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_MOVABLE_BOX_H diff --git a/lib/libcxx/include/__ranges/non_propagating_cache.h b/lib/libcxx/include/__ranges/non_propagating_cache.h index d50c577fc3..f522396204 100644 --- a/lib/libcxx/include/__ranges/non_propagating_cache.h +++ b/lib/libcxx/include/__ranges/non_propagating_cache.h @@ -16,7 +16,6 @@ #include <__memory/addressof.h> #include <__utility/forward.h> #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { // __non_propagating_cache is a helper type that allows storing an optional value in it, @@ -44,10 +43,11 @@ namespace ranges { // This helper class is needed to perform copy and move elision when // constructing the contained type from an iterator. struct __wrapper { - template - constexpr explicit __wrapper(__forward_tag, _Args&& ...__args) : __t_(std::forward<_Args>(__args)...) { } - template - constexpr explicit __wrapper(__from_tag, _Fn const& __f) : __t_(__f()) { } + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __wrapper(__forward_tag, _Args&&... __args) + : __t_(std::forward<_Args>(__args)...) {} + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit __wrapper(__from_tag, _Fn const& __f) : __t_(__f()) {} _Tp __t_; }; @@ -107,7 +107,7 @@ namespace ranges { struct __empty_cache { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/owning_view.h b/lib/libcxx/include/__ranges/owning_view.h index e150f6d9f2..c846de899b 100644 --- a/lib/libcxx/include/__ranges/owning_view.h +++ b/lib/libcxx/include/__ranges/owning_view.h @@ -20,16 +20,19 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include #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 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -38,11 +41,11 @@ namespace ranges { _Rp __r_ = _Rp(); public: - owning_view() requires default_initializable<_Rp> = default; + _LIBCPP_HIDE_FROM_ABI owning_view() requires default_initializable<_Rp> = default; _LIBCPP_HIDE_FROM_ABI constexpr owning_view(_Rp&& __r) : __r_(std::move(__r)) {} - owning_view(owning_view&&) = default; - owning_view& operator=(owning_view&&) = default; + _LIBCPP_HIDE_FROM_ABI owning_view(owning_view&&) = default; + _LIBCPP_HIDE_FROM_ABI owning_view& operator=(owning_view&&) = default; _LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; } @@ -76,8 +79,10 @@ public: } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_OWNING_VIEW_H diff --git a/lib/libcxx/include/__ranges/range_adaptor.h b/lib/libcxx/include/__ranges/range_adaptor.h index 37e48179e3..2688e4cd04 100644 --- a/lib/libcxx/include/__ranges/range_adaptor.h +++ b/lib/libcxx/include/__ranges/range_adaptor.h @@ -18,17 +18,22 @@ #include <__functional/compose.h> #include <__functional/invoke.h> #include <__ranges/concepts.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #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 +#if _LIBCPP_STD_VER >= 20 // CRTP base that one can derive from in order to be considered a range adaptor closure // by the library. When deriving from this class, a pipe operator will be provided to @@ -42,7 +47,7 @@ struct __range_adaptor_closure; // i.e. something that can be called via the `x | f` notation. template struct __range_adaptor_closure_t : _Fn, __range_adaptor_closure<__range_adaptor_closure_t<_Fn>> { - constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { } + _LIBCPP_HIDE_FROM_ABI constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { } }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__range_adaptor_closure_t); @@ -70,8 +75,10 @@ struct __range_adaptor_closure { { return __range_adaptor_closure_t(std::__compose(std::forward<_OtherClosure>(__c2), std::forward<_Closure>(__c1))); } }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_RANGE_ADAPTOR_H diff --git a/lib/libcxx/include/__ranges/rbegin.h b/lib/libcxx/include/__ranges/rbegin.h index 26b47321de..1ceb1116d6 100644 --- a/lib/libcxx/include/__ranges/rbegin.h +++ b/lib/libcxx/include/__ranges/rbegin.h @@ -17,8 +17,11 @@ #include <__iterator/readable_traits.h> #include <__iterator/reverse_iterator.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [ranges.access.rbegin] @@ -124,7 +127,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/ref_view.h b/lib/libcxx/include/__ranges/ref_view.h index 1e5f7466f3..be32b81242 100644 --- a/lib/libcxx/include/__ranges/ref_view.h +++ b/lib/libcxx/include/__ranges/ref_view.h @@ -24,8 +24,9 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/is_object.h> +#include <__utility/declval.h> #include <__utility/forward.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -33,7 +34,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -81,7 +82,7 @@ public: inline constexpr bool enable_borrowed_range> = true; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/rend.h b/lib/libcxx/include/__ranges/rend.h index d2987e9fa8..7ee574ccfa 100644 --- a/lib/libcxx/include/__ranges/rend.h +++ b/lib/libcxx/include/__ranges/rend.h @@ -18,8 +18,11 @@ #include <__iterator/reverse_iterator.h> #include <__ranges/access.h> #include <__ranges/rbegin.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.access.rend] @@ -128,7 +131,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/repeat_view.h b/lib/libcxx/include/__ranges/repeat_view.h new file mode 100644 index 0000000000..fddf4baac8 --- /dev/null +++ b/lib/libcxx/include/__ranges/repeat_view.h @@ -0,0 +1,260 @@ +// -*- 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___RANGES_REPEAT_VIEW_H +#define _LIBCPP___RANGES_REPEAT_VIEW_H + +#include <__concepts/constructible.h> +#include <__concepts/same_as.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/unreachable_sentinel.h> +#include <__memory/addressof.h> +#include <__ranges/iota_view.h> +#include <__ranges/movable_box.h> +#include <__ranges/view_interface.h> +#include <__type_traits/is_object.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cv.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/piecewise_construct.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template +concept __integer_like_with_usable_difference_type = + __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>); + +template +struct __repeat_view_iterator_difference { + using type = _IotaDiffT<_Tp>; +}; + +template <__signed_integer_like _Tp> +struct __repeat_view_iterator_difference<_Tp> { + using type = _Tp; +}; + +template +using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type; + +namespace views::__drop { +struct __fn; +} // namespace views::__drop + +namespace views::__take { +struct __fn; +} // namespace views::__take + +template + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) +class repeat_view : public view_interface> { + friend struct views::__take::__fn; + friend struct views::__drop::__fn; + class __iterator; + +public: + _LIBCPP_HIDE_FROM_ABI repeat_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound()) + requires copy_constructible<_Tp> + : __value_(in_place, __value), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) + : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); + } + + template + requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( + piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) + : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), + __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT( + __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const + requires(!same_as<_Bound, unreachable_sentinel_t>) + { + return __iterator(std::addressof(*__value_), __bound_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires(!same_as<_Bound, unreachable_sentinel_t>) + { + return std::__to_unsigned_like(__bound_); + } + +private: + __movable_box<_Tp> __value_; + _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); +}; + +template +repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + +// [range.repeat.iterator] +template + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) +class repeat_view<_Tp, _Bound>::__iterator { + friend class repeat_view; + + using _IndexT = conditional_t, ptrdiff_t, _Bound>; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) + : __value_(__value), __current_(__bound_sentinel) {} + +public: + using iterator_concept = random_access_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = _Tp; + using difference_type = __repeat_view_iterator_difference_t<_IndexT>; + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ > 0, "The value of bound must be greater than or equal to 0"); + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0"); + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0"); + __current_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { + return static_cast(__x.__current_) - static_cast(__y.__current_); + } + +private: + const _Tp* __value_ = nullptr; + _IndexT __current_ = _IndexT(); +}; + +// clang-format off +namespace views { +namespace __repeat { +struct __fn { + template + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) + -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) + { return ranges::repeat_view(std::forward<_Tp>(__value)); } + + + template + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) + -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) + { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } +}; +} // namespace __repeat +// clang-format on + +inline namespace __cpo { +inline constexpr auto repeat = __repeat::__fn{}; +} // namespace __cpo +} // namespace views + +template +inline constexpr bool __is_repeat_specialization = false; + +template +inline constexpr bool __is_repeat_specialization> = true; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_REPEAT_VIEW_H diff --git a/lib/libcxx/include/__ranges/reverse_view.h b/lib/libcxx/include/__ranges/reverse_view.h index d7b1378054..01d1b97b3c 100644 --- a/lib/libcxx/include/__ranges/reverse_view.h +++ b/lib/libcxx/include/__ranges/reverse_view.h @@ -24,9 +24,10 @@ #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -184,7 +185,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/single_view.h b/lib/libcxx/include/__ranges/single_view.h index 5c4b91869c..5724e2d1b6 100644 --- a/lib/libcxx/include/__ranges/single_view.h +++ b/lib/libcxx/include/__ranges/single_view.h @@ -12,13 +12,15 @@ #include <__concepts/constructible.h> #include <__config> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_object.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,51 +28,51 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { - template - requires is_object_v<_Tp> - class single_view : public view_interface> { - __copyable_box<_Tp> __value_; +# if _LIBCPP_STD_VER >= 23 +template +# else +template +# endif + requires is_object_v<_Tp> +class single_view : public view_interface> { + __movable_box<_Tp> __value_; - public: - _LIBCPP_HIDE_FROM_ABI - single_view() requires default_initializable<_Tp> = default; +public: + _LIBCPP_HIDE_FROM_ABI single_view() + requires default_initializable<_Tp> + = default; - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(const _Tp& __t) : __value_(in_place, __t) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(const _Tp& __t) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + : __value_(in_place, __t) { + } - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} - template - requires constructible_from<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(in_place_t, _Args&&... __args) + template + requires constructible_from<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(in_place_t, _Args&&... __args) : __value_{in_place, std::forward<_Args>(__args)...} {} - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* begin() noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* begin() noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* begin() const noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* begin() const noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* end() noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* end() noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* end() const noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* end() const noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - static constexpr size_t size() noexcept { return 1; } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t size() noexcept { return 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* data() noexcept { return __value_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* data() noexcept { return __value_.operator->(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* data() const noexcept { return __value_.operator->(); } - }; + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* data() const noexcept { return __value_.operator->(); } +}; template single_view(_Tp) -> single_view<_Tp>; @@ -95,7 +97,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/size.h b/lib/libcxx/include/__ranges/size.h index 0ac8d63063..f22dd1ff7b 100644 --- a/lib/libcxx/include/__ranges/size.h +++ b/lib/libcxx/include/__ranges/size.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -141,7 +141,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/split_view.h b/lib/libcxx/include/__ranges/split_view.h index 6ebe5a43ed..a27ac4ef7a 100644 --- a/lib/libcxx/include/__ranges/split_view.h +++ b/lib/libcxx/include/__ranges/split_view.h @@ -75,13 +75,14 @@ public: requires default_initializable<_View> && default_initializable<_Pattern> = default; - _LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 split_view(_View __base, _Pattern __pattern) : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} template requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view>> - _LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 + split_view(_Range&& __range, range_value_t<_Range> __elem) : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& diff --git a/lib/libcxx/include/__ranges/subrange.h b/lib/libcxx/include/__ranges/subrange.h index 2d9e4cc7e5..75f9284a58 100644 --- a/lib/libcxx/include/__ranges/subrange.h +++ b/lib/libcxx/include/__ranges/subrange.h @@ -29,9 +29,9 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple_dir/pair_like.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/pair_like.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> #include <__type_traits/conditional.h> #include <__type_traits/decay.h> #include <__type_traits/is_pointer.h> @@ -46,9 +46,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template @@ -82,7 +85,7 @@ namespace ranges { private: static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics - struct _Empty { constexpr _Empty(auto) noexcept { } }; + struct _Empty { _LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept { } }; using _Size = conditional_t<_StoreSize, make_unsigned_t>, _Empty>; _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter(); _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent(); @@ -105,7 +108,7 @@ namespace ranges { : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) { if constexpr (sized_sentinel_for<_Sent, _Iter>) - _LIBCPP_ASSERT((__end_ - __begin_) == static_cast>(__n), + _LIBCPP_ASSERT_UNCATEGORIZED((__end_ - __begin_) == static_cast>(__n), "std::ranges::subrange was passed an invalid size hint"); } @@ -284,8 +287,10 @@ struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { using type = _Sp; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_SUBRANGE_H diff --git a/lib/libcxx/include/__ranges/take_view.h b/lib/libcxx/include/__ranges/take_view.h index bea3862cd7..4204017d92 100644 --- a/lib/libcxx/include/__ranges/take_view.h +++ b/lib/libcxx/include/__ranges/take_view.h @@ -31,14 +31,18 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/iota_view.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -49,7 +53,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -64,9 +68,10 @@ public: _LIBCPP_HIDE_FROM_ABI take_view() requires default_initializable<_View> = default; - _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count) + _LIBCPP_HIDE_FROM_ABI + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_view(_View __base, range_difference_t<_View> __count) : __base_(std::move(__base)), __count_(__count) { - _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero"); + _LIBCPP_ASSERT_UNCATEGORIZED(__count >= 0, "count has to be greater than or equal to zero"); } _LIBCPP_HIDE_FROM_ABI @@ -297,6 +302,31 @@ struct __fn { *ranges::begin(__rng), *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) ); } +// clang-format off +#if _LIBCPP_STD_VER >= 23 + // [range.take.overview]: the `repeat_view` "_RawRange models sized_range" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype( views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) + { return views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } + + // [range.take.overview]: the `repeat_view` "otherwise" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, static_cast<_Dist>(__n)))) + -> decltype( views::repeat(*__range.__value_, static_cast<_Dist>(__n))) + { return views::repeat(*__range.__value_, static_cast<_Dist>(__n)); } +#endif +// clang-format on // [range.take.overview]: the "otherwise" case. template > _Np, @@ -304,6 +334,9 @@ struct __fn { // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. requires (!(__is_empty_view<_RawRange> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__is_iota_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || @@ -334,7 +367,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__ranges/take_while_view.h b/lib/libcxx/include/__ranges/take_while_view.h index 77d7390dce..b4bdd1865d 100644 --- a/lib/libcxx/include/__ranges/take_while_view.h +++ b/lib/libcxx/include/__ranges/take_while_view.h @@ -20,7 +20,7 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> #include <__type_traits/decay.h> @@ -60,14 +60,14 @@ class take_while_view : public view_interface> { class __sentinel; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; public: _LIBCPP_HIDE_FROM_ABI take_while_view() requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI constexpr take_while_view(_View __base, _Pred __pred) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred) : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& diff --git a/lib/libcxx/include/__ranges/to.h b/lib/libcxx/include/__ranges/to.h new file mode 100644 index 0000000000..95c300bfa6 --- /dev/null +++ b/lib/libcxx/include/__ranges/to.h @@ -0,0 +1,247 @@ +// -*- 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___RANGES_TO_H +#define _LIBCPP___RANGES_TO_H + +#include <__algorithm/ranges_copy.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/insert_iterator.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/from_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/transform_view.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/type_identity.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +// TODO(clang-15): in the Standard, it's a `constexpr bool` variable, not a concept, but constexpr variables don't +// short-circuit properly on Clang 15 (fixed in later versions), so use a concept as a workaround. +template +concept __reservable_container = sized_range<_Container> && requires(_Container& __c, range_size_t<_Container> __n) { + __c.reserve(__n); + { __c.capacity() } -> same_as; + { __c.max_size() } -> same_as; +}; + +template +constexpr bool __container_insertable = requires(_Container& __c, _Ref&& __ref) { + requires( + requires { __c.push_back(std::forward<_Ref>(__ref)); } || + requires { __c.insert(__c.end(), std::forward<_Ref>(__ref)); }); +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __container_inserter(_Container& __c) { + if constexpr (requires { __c.push_back(std::declval<_Ref>()); }) { + return std::back_inserter(__c); + } else { + return std::inserter(__c, __c.end()); + } +} + +// Note: making this a concept allows short-circuiting the second condition. +template +concept __try_non_recursive_conversion = + !input_range<_Container> || convertible_to, range_value_t<_Container>>; + +template +concept __constructible_from_iter_pair = + common_range<_Range> && requires { typename iterator_traits>::iterator_category; } && + derived_from>::iterator_category, input_iterator_tag> && + constructible_from<_Container, iterator_t<_Range>, sentinel_t<_Range>, _Args...>; + +template +concept __always_false = false; + +// `ranges::to` base template -- the `_Container` type is a simple type template parameter. +template + requires(!view<_Container>) +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { + // Mandates: C is a cv-unqualified class type. + static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const"); + static_assert( + !is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile"); + + // First see if the non-recursive case applies -- the conversion target is either: + // - a range with a convertible value type; + // - a non-range type which might support being created from the input argument(s) (e.g. an `optional`). + if constexpr (__try_non_recursive_conversion<_Container, _Range>) { + // Case 1 -- construct directly from the given range. + if constexpr (constructible_from<_Container, _Range, _Args...>) { + return _Container(std::forward<_Range>(__range), std::forward<_Args>(__args)...); + } + + // Case 2 -- construct using the `from_range_t` tagged constructor. + else if constexpr (constructible_from<_Container, from_range_t, _Range, _Args...>) { + return _Container(from_range, std::forward<_Range>(__range), std::forward<_Args>(__args)...); + } + + // Case 3 -- construct from a begin-end iterator pair. + else if constexpr (__constructible_from_iter_pair<_Container, _Range, _Args...>) { + return _Container(ranges::begin(__range), ranges::end(__range), std::forward<_Args>(__args)...); + } + + // Case 4 -- default-construct (or construct from the extra arguments) and insert, reserving the size if possible. + else if constexpr (constructible_from<_Container, _Args...> && + __container_insertable<_Container, range_reference_t<_Range>>) { + _Container __result(std::forward<_Args>(__args)...); + if constexpr (sized_range<_Range> && __reservable_container<_Container>) { + __result.reserve(static_cast>(ranges::size(__range))); + } + + ranges::copy(__range, ranges::__container_inserter>(__result)); + + return __result; + + } else { + static_assert(__always_false<_Container>, "ranges::to: unable to convert to the given container type."); + } + + // Try the recursive case. + } else if constexpr (input_range>) { + return ranges::to<_Container>( + __range | views::transform([](auto&& __elem) { + return ranges::to>(std::forward(__elem)); + }), + std::forward<_Args>(__args)...); + + } else { + static_assert(__always_false<_Container>, "ranges::to: unable to convert to the given container type."); + } +} + +template +struct __minimal_input_iterator { + using iterator_category = input_iterator_tag; + using value_type = range_value_t<_Range>; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t<_Range>; + + reference operator*() const; + pointer operator->() const; + __minimal_input_iterator& operator++(); + __minimal_input_iterator operator++(int); + bool operator==(const __minimal_input_iterator&) const; +}; + +// Deduces the full type of the container from the given template template parameter. +template