diff --git a/lib/libcxx/include/__algorithm/adjacent_find.h b/lib/libcxx/include/__algorithm/adjacent_find.h index 0a2aa055c1..29ad83f968 100644 --- a/lib/libcxx/include/__algorithm/adjacent_find.h +++ b/lib/libcxx/include/__algorithm/adjacent_find.h @@ -10,17 +10,14 @@ #ifndef _LIBCPP___ALGORITHM_ADJACENT_FIND_H #define _LIBCPP___ALGORITHM_ADJACENT_FIND_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -46,6 +43,4 @@ 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 7d6ed50859..817a4bc89c 100644 --- a/lib/libcxx/include/__algorithm/all_of.h +++ b/lib/libcxx/include/__algorithm/all_of.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_ALL_OF_H diff --git a/lib/libcxx/include/__algorithm/any_of.h b/lib/libcxx/include/__algorithm/any_of.h index d5a6c094a6..f4116d9130 100644 --- a/lib/libcxx/include/__algorithm/any_of.h +++ b/lib/libcxx/include/__algorithm/any_of.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_ANY_OF_H diff --git a/lib/libcxx/include/__algorithm/binary_search.h b/lib/libcxx/include/__algorithm/binary_search.h index 766f5da162..2558dd0b27 100644 --- a/lib/libcxx/include/__algorithm/binary_search.h +++ b/lib/libcxx/include/__algorithm/binary_search.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_BINARY_SEARCH_H #define _LIBCPP___ALGORITHM_BINARY_SEARCH_H -#include <__config> #include <__algorithm/comp.h> -#include <__algorithm/lower_bound.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/lower_bound.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -53,9 +50,6 @@ binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __va __less::value_type, _Tp>()); } - _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_BINARY_SEARCH_H diff --git a/lib/libcxx/include/__algorithm/clamp.h b/lib/libcxx/include/__algorithm/clamp.h index f8eba03cf8..a51c1015be 100644 --- a/lib/libcxx/include/__algorithm/clamp.h +++ b/lib/libcxx/include/__algorithm/clamp.h @@ -9,21 +9,17 @@ #ifndef _LIBCPP___ALGORITHM_CLAMP_H #define _LIBCPP___ALGORITHM_CLAMP_H +#include <__algorithm/comp.h> #include <__config> #include <__debug> -#include <__algorithm/comp.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 > 14 -// clamp template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR @@ -47,6 +43,4 @@ clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_CLAMP_H diff --git a/lib/libcxx/include/__algorithm/comp.h b/lib/libcxx/include/__algorithm/comp.h index 2039cf7b39..b3f971e4f0 100644 --- a/lib/libcxx/include/__algorithm/comp.h +++ b/lib/libcxx/include/__algorithm/comp.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD // I'd like to replace these with _VSTD::equal_to, but can't because: @@ -92,6 +89,4 @@ struct __less<_T1, const _T1> _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COMP_H diff --git a/lib/libcxx/include/__algorithm/comp_ref_type.h b/lib/libcxx/include/__algorithm/comp_ref_type.h index b3bca82c09..0802d2496f 100644 --- a/lib/libcxx/include/__algorithm/comp_ref_type.h +++ b/lib/libcxx/include/__algorithm/comp_ref_type.h @@ -10,15 +10,16 @@ #define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H #include <__config> -#include + +#ifdef _LIBCPP_DEBUG +# include <__debug> +# include <__utility/declval.h> +#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #ifdef _LIBCPP_DEBUG @@ -27,11 +28,11 @@ template struct __debug_less { _Compare &__comp_; - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 __debug_less(_Compare& __c) : __comp_(__c) {} template - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _Tp& __x, const _Up& __y) { bool __r = __comp_(__x, __y); @@ -41,7 +42,7 @@ struct __debug_less } template - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(_Tp& __x, _Up& __y) { bool __r = __comp_(__x, __y); @@ -51,7 +52,7 @@ struct __debug_less } template - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 inline _LIBCPP_INLINE_VISIBILITY decltype((void)declval<_Compare&>()( declval<_LHS &>(), declval<_RHS &>())) @@ -61,7 +62,7 @@ struct __debug_less } template - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 inline _LIBCPP_INLINE_VISIBILITY void __do_compare_assert(long, _LHS &, _RHS &) {} }; @@ -73,15 +74,12 @@ struct __comp_ref_type { // Pass the comparator by lvalue reference. Or in debug mode, using a // debugging wrapper that stores a reference. #ifndef _LIBCPP_DEBUG - typedef typename add_lvalue_reference<_Comp>::type type; + typedef _Comp& type; #else typedef __debug_less<_Comp> type; #endif }; - _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COMP_REF_TYPE_H diff --git a/lib/libcxx/include/__algorithm/copy.h b/lib/libcxx/include/__algorithm/copy.h index 9db7434c04..65f0e0b0ef 100644 --- a/lib/libcxx/include/__algorithm/copy.h +++ b/lib/libcxx/include/__algorithm/copy.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_COPY_H #define _LIBCPP___ALGORITHM_COPY_H -#include <__config> #include <__algorithm/unwrap_iter.h> +#include <__config> #include <__iterator/iterator_traits.h> #include #include @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD // copy @@ -77,6 +74,4 @@ copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COPY_H diff --git a/lib/libcxx/include/__algorithm/copy_backward.h b/lib/libcxx/include/__algorithm/copy_backward.h index 03a9c5f2d0..ac733290ab 100644 --- a/lib/libcxx/include/__algorithm/copy_backward.h +++ b/lib/libcxx/include/__algorithm/copy_backward.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H #define _LIBCPP___ALGORITHM_COPY_BACKWARD_H -#include <__config> #include <__algorithm/unwrap_iter.h> +#include <__config> #include <__iterator/iterator_traits.h> #include #include @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -79,6 +76,4 @@ copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H diff --git a/lib/libcxx/include/__algorithm/copy_if.h b/lib/libcxx/include/__algorithm/copy_if.h index 153304c7a7..d32514d999 100644 --- a/lib/libcxx/include/__algorithm/copy_if.h +++ b/lib/libcxx/include/__algorithm/copy_if.h @@ -10,18 +10,11 @@ #define _LIBCPP___ALGORITHM_COPY_IF_H #include <__config> -#include <__algorithm/unwrap_iter.h> -#include <__iterator/iterator_traits.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 @@ -43,6 +36,4 @@ copy_if(_InputIterator __first, _InputIterator __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/copy_n.h b/lib/libcxx/include/__algorithm/copy_n.h index bbfeb8686f..cdcc0d50db 100644 --- a/lib/libcxx/include/__algorithm/copy_n.h +++ b/lib/libcxx/include/__algorithm/copy_n.h @@ -9,20 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_COPY_N_H #define _LIBCPP___ALGORITHM_COPY_N_H -#include <__config> #include <__algorithm/copy.h> -#include <__algorithm/unwrap_iter.h> +#include <__config> #include <__iterator/iterator_traits.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 @@ -60,13 +55,12 @@ typename enable_if >::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) { + typedef typename iterator_traits<_InputIterator>::difference_type difference_type; typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; _IntegralSize __n = __orig_n; - return _VSTD::copy(__first, __first + __n, __result); + return _VSTD::copy(__first, __first + difference_type(__n), __result); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COPY_N_H diff --git a/lib/libcxx/include/__algorithm/count.h b/lib/libcxx/include/__algorithm/count.h index 7f2d1954cd..81a2c186f8 100644 --- a/lib/libcxx/include/__algorithm/count.h +++ b/lib/libcxx/include/__algorithm/count.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -35,6 +32,4 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_C _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COUNT_H diff --git a/lib/libcxx/include/__algorithm/count_if.h b/lib/libcxx/include/__algorithm/count_if.h index a5efffb926..00f5d671da 100644 --- a/lib/libcxx/include/__algorithm/count_if.h +++ b/lib/libcxx/include/__algorithm/count_if.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -35,6 +32,4 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_C _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_COUNT_IF_H diff --git a/lib/libcxx/include/__algorithm/equal.h b/lib/libcxx/include/__algorithm/equal.h index bc67559819..4c9ad05ad6 100644 --- a/lib/libcxx/include/__algorithm/equal.h +++ b/lib/libcxx/include/__algorithm/equal.h @@ -10,18 +10,15 @@ #ifndef _LIBCPP___ALGORITHM_EQUAL_H #define _LIBCPP___ALGORITHM_EQUAL_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> -#include // FIXME: replace with <__iterator/distance.h> when it lands #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -60,14 +57,14 @@ __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _Random if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) return false; return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, - typename add_lvalue_reference<_BinaryPredicate>::type>(__first1, __last1, __first2, __pred); + _BinaryPredicate&>(__first1, __last1, __first2, __pred); } template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred) { - return _VSTD::__equal::type>( + return _VSTD::__equal<_BinaryPredicate&>( __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_InputIterator1>::iterator_category(), typename iterator_traits<_InputIterator2>::iterator_category()); } @@ -85,6 +82,4 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_EQUAL_H diff --git a/lib/libcxx/include/__algorithm/equal_range.h b/lib/libcxx/include/__algorithm/equal_range.h index 9694dae950..e13f0bdd96 100644 --- a/lib/libcxx/include/__algorithm/equal_range.h +++ b/lib/libcxx/include/__algorithm/equal_range.h @@ -9,21 +9,18 @@ #ifndef _LIBCPP___ALGORITHM_EQUAL_RANGE_H #define _LIBCPP___ALGORITHM_EQUAL_RANGE_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/half_positive.h> #include <__algorithm/lower_bound.h> #include <__algorithm/upper_bound.h> +#include <__config> #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 @@ -82,6 +79,4 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H diff --git a/lib/libcxx/include/__algorithm/fill.h b/lib/libcxx/include/__algorithm/fill.h index 4fefe86536..0cb36b02c8 100644 --- a/lib/libcxx/include/__algorithm/fill.h +++ b/lib/libcxx/include/__algorithm/fill.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_FILL_H #define _LIBCPP___ALGORITHM_FILL_H -#include <__config> #include <__algorithm/fill_n.h> +#include <__config> #include <__iterator/iterator_traits.h> #include @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -50,6 +47,4 @@ fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FILL_H diff --git a/lib/libcxx/include/__algorithm/fill_n.h b/lib/libcxx/include/__algorithm/fill_n.h index 34a245edb5..857ac14157 100644 --- a/lib/libcxx/include/__algorithm/fill_n.h +++ b/lib/libcxx/include/__algorithm/fill_n.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -42,6 +39,4 @@ fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FILL_N_H diff --git a/lib/libcxx/include/__algorithm/find.h b/lib/libcxx/include/__algorithm/find.h index bc593dc542..2a6dfbe41a 100644 --- a/lib/libcxx/include/__algorithm/find.h +++ b/lib/libcxx/include/__algorithm/find.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ find(_InputIterator __first, _InputIterator __last, const _Tp& __value_) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FIND_H diff --git a/lib/libcxx/include/__algorithm/find_end.h b/lib/libcxx/include/__algorithm/find_end.h index f4277f003a..dd0f7d7ac0 100644 --- a/lib/libcxx/include/__algorithm/find_end.h +++ b/lib/libcxx/include/__algorithm/find_end.h @@ -10,18 +10,14 @@ #ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H #define _LIBCPP___ALGORITHM_FIND_END_OF_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.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 @@ -99,14 +95,16 @@ template ::difference_type _D1; + typedef typename iterator_traits<_RandomAccessIterator2>::difference_type _D2; // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern - typename iterator_traits<_RandomAccessIterator2>::difference_type __len2 = __last2 - __first2; + _D2 __len2 = __last2 - __first2; if (__len2 == 0) return __last1; - typename iterator_traits<_RandomAccessIterator1>::difference_type __len1 = __last1 - __first1; + _D1 __len1 = __last1 - __first1; if (__len1 < __len2) return __last1; - const _RandomAccessIterator1 __s = __first1 + (__len2 - 1); // End of pattern match can't go before here + const _RandomAccessIterator1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here _RandomAccessIterator1 __l1 = __last1; _RandomAccessIterator2 __l2 = __last2; --__l2; @@ -134,7 +132,7 @@ template ::type>( + return _VSTD::__find_end<_BinaryPredicate&>( __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), typename iterator_traits<_ForwardIterator2>::iterator_category()); } @@ -149,6 +147,4 @@ find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FIND_END_OF_H diff --git a/lib/libcxx/include/__algorithm/find_first_of.h b/lib/libcxx/include/__algorithm/find_first_of.h index d956c8dda2..69354f6176 100644 --- a/lib/libcxx/include/__algorithm/find_first_of.h +++ b/lib/libcxx/include/__algorithm/find_first_of.h @@ -10,17 +10,14 @@ #ifndef _LIBCPP___ALGORITHM_FIND_FIRST_OF_H #define _LIBCPP___ALGORITHM_FIND_FIRST_OF_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -52,6 +49,4 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_C _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FIND_FIRST_OF_H diff --git a/lib/libcxx/include/__algorithm/find_if.h b/lib/libcxx/include/__algorithm/find_if.h index 456cc5b0a3..a94196a16a 100644 --- a/lib/libcxx/include/__algorithm/find_if.h +++ b/lib/libcxx/include/__algorithm/find_if.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FIND_IF_H diff --git a/lib/libcxx/include/__algorithm/find_if_not.h b/lib/libcxx/include/__algorithm/find_if_not.h index d7d25160cc..e057db5efa 100644 --- a/lib/libcxx/include/__algorithm/find_if_not.h +++ b/lib/libcxx/include/__algorithm/find_if_not.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FIND_IF_NOT_H diff --git a/lib/libcxx/include/__algorithm/for_each.h b/lib/libcxx/include/__algorithm/for_each.h index e71a36a1de..1612ffa5c0 100644 --- a/lib/libcxx/include/__algorithm/for_each.h +++ b/lib/libcxx/include/__algorithm/for_each.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Function for_eac _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FOR_EACH_H diff --git a/lib/libcxx/include/__algorithm/for_each_n.h b/lib/libcxx/include/__algorithm/for_each_n.h index 77f6c86214..00e3fb9c1d 100644 --- a/lib/libcxx/include/__algorithm/for_each_n.h +++ b/lib/libcxx/include/__algorithm/for_each_n.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 @@ -42,6 +39,4 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator fo _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H diff --git a/lib/libcxx/include/__algorithm/generate.h b/lib/libcxx/include/__algorithm/generate.h index d3e1133e2b..10834cdb74 100644 --- a/lib/libcxx/include/__algorithm/generate.h +++ b/lib/libcxx/include/__algorithm/generate.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -31,6 +28,4 @@ generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_GENERATE_H diff --git a/lib/libcxx/include/__algorithm/generate_n.h b/lib/libcxx/include/__algorithm/generate_n.h index c312598586..595007cdd3 100644 --- a/lib/libcxx/include/__algorithm/generate_n.h +++ b/lib/libcxx/include/__algorithm/generate_n.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -35,6 +32,4 @@ generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_GENERATE_N_H diff --git a/lib/libcxx/include/__algorithm/half_positive.h b/lib/libcxx/include/__algorithm/half_positive.h index b03efc495b..5d36ff5da9 100644 --- a/lib/libcxx/include/__algorithm/half_positive.h +++ b/lib/libcxx/include/__algorithm/half_positive.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD // Perform division by two quickly for positive integers (llvm.org/PR39129) @@ -49,6 +46,4 @@ __half_positive(_Tp __value) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_HALF_POSITIVE_H diff --git a/lib/libcxx/include/__algorithm/in_in_out_result.h b/lib/libcxx/include/__algorithm/in_in_out_result.h new file mode 100644 index 0000000000..8d29b7b69b --- /dev/null +++ b/lib/libcxx/include/__algorithm/in_in_out_result.h @@ -0,0 +1,54 @@ +// -*- 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_IN_IN_OUT_RESULT_H +#define _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +namespace ranges { + +template +struct in_in_out_result { + [[no_unique_address]] _I1 in1; + [[no_unique_address]] _I2 in2; + [[no_unique_address]] _O1 out; + + template + requires convertible_to && convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_out_result<_II1, _II2, _OO1>() const& { + return {in1, in2, out}; + } + + template + requires convertible_to<_I1, _II1> && convertible_to<_I2, _II2> && convertible_to<_O1, _OO1> + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_out_result<_II1, _II2, _OO1>() && { + return {_VSTD::move(in1), _VSTD::move(in2), _VSTD::move(out)}; + } +}; + +} // namespace ranges + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H diff --git a/lib/libcxx/include/__algorithm/in_in_result.h b/lib/libcxx/include/__algorithm/in_in_result.h new file mode 100644 index 0000000000..c8fe43d039 --- /dev/null +++ b/lib/libcxx/include/__algorithm/in_in_result.h @@ -0,0 +1,51 @@ +// -*- 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_IN_IN_RESULT_H +#define _LIBCPP___ALGORITHM_IN_IN_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace ranges { + +template +struct in_in_result { + [[no_unique_address]] _I1 in1; + [[no_unique_address]] _I2 in2; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_result<_II1, _II2>() const & { + return {in1, in2}; + } + + template + requires convertible_to<_I1, _II1> && convertible_to<_I2, _II2> + _LIBCPP_HIDE_FROM_ABI constexpr + operator in_in_result<_II1, _II2>() && { return {_VSTD::move(in1), _VSTD::move(in2)}; } +}; + +} // namespace ranges + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_IN_RESULT_H diff --git a/lib/libcxx/include/__algorithm/in_out_result.h b/lib/libcxx/include/__algorithm/in_out_result.h new file mode 100644 index 0000000000..dcf72d08dd --- /dev/null +++ b/lib/libcxx/include/__algorithm/in_out_result.h @@ -0,0 +1,54 @@ +// -*- 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_IN_OUT_RESULT_H +#define _LIBCPP___ALGORITHM_IN_OUT_RESULT_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +namespace ranges { + +template +struct in_out_result { + [[no_unique_address]] _InputIterator in; + [[no_unique_address]] _OutputIterator out; + + template + requires convertible_to && convertible_to + _LIBCPP_HIDE_FROM_ABI + constexpr operator in_out_result<_InputIterator2, _OutputIterator2>() const & { + return {in, out}; + } + + template + requires convertible_to<_InputIterator, _InputIterator2> && convertible_to<_OutputIterator, _OutputIterator2> + _LIBCPP_HIDE_FROM_ABI + constexpr operator in_out_result<_InputIterator2, _OutputIterator2>() && { + return {_VSTD::move(in), _VSTD::move(out)}; + } +}; + +} // namespace ranges + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_IN_OUT_RESULT_H diff --git a/lib/libcxx/include/__algorithm/includes.h b/lib/libcxx/include/__algorithm/includes.h index ff298a5111..9d0bc694c0 100644 --- a/lib/libcxx/include/__algorithm/includes.h +++ b/lib/libcxx/include/__algorithm/includes.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_INCLUDES_H #define _LIBCPP___ALGORITHM_INCLUDES_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -62,6 +59,4 @@ includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_INCLUDES_H diff --git a/lib/libcxx/include/__algorithm/inplace_merge.h b/lib/libcxx/include/__algorithm/inplace_merge.h index c74633a74c..e6f1efc011 100644 --- a/lib/libcxx/include/__algorithm/inplace_merge.h +++ b/lib/libcxx/include/__algorithm/inplace_merge.h @@ -9,14 +9,14 @@ #ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H #define _LIBCPP___ALGORITHM_INPLACE_MERGE_H -#include <__config> -#include <__algorithm/comp_ref_type.h> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> #include <__algorithm/lower_bound.h> #include <__algorithm/min.h> #include <__algorithm/move.h> #include <__algorithm/rotate.h> #include <__algorithm/upper_bound.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> #include diff --git a/lib/libcxx/include/__algorithm/is_heap.h b/lib/libcxx/include/__algorithm/is_heap.h index bc3682d471..925ba8bfb8 100644 --- a/lib/libcxx/include/__algorithm/is_heap.h +++ b/lib/libcxx/include/__algorithm/is_heap.h @@ -9,18 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_IS_HEAP_H #define _LIBCPP___ALGORITHM_IS_HEAP_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> #include <__algorithm/is_heap_until.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -29,7 +27,8 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - return _VSTD::is_heap_until(__first, __last, __comp) == __last; + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__is_heap_until<_Comp_ref>(__first, __last, __comp) == __last; } template @@ -43,6 +42,4 @@ is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_IS_HEAP_H diff --git a/lib/libcxx/include/__algorithm/is_heap_until.h b/lib/libcxx/include/__algorithm/is_heap_until.h index 8c52edb7d4..aa23b6d039 100644 --- a/lib/libcxx/include/__algorithm/is_heap_until.h +++ b/lib/libcxx/include/__algorithm/is_heap_until.h @@ -9,22 +9,20 @@ #ifndef _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H #define _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator -is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator +__is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; difference_type __len = __last - __first; @@ -49,17 +47,21 @@ is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp return __last; } +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator +is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +{ + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__is_heap_until<_Comp_ref>(__first, __last, __comp); +} + template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_RandomAccessIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _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::value_type>()); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H diff --git a/lib/libcxx/include/__algorithm/is_partitioned.h b/lib/libcxx/include/__algorithm/is_partitioned.h index 43de6650cb..e5b2214aa0 100644 --- a/lib/libcxx/include/__algorithm/is_partitioned.h +++ b/lib/libcxx/include/__algorithm/is_partitioned.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -38,6 +35,4 @@ is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_IS_PARTITIONED_H diff --git a/lib/libcxx/include/__algorithm/is_permutation.h b/lib/libcxx/include/__algorithm/is_permutation.h index 0545eb7637..344aa763ad 100644 --- a/lib/libcxx/include/__algorithm/is_permutation.h +++ b/lib/libcxx/include/__algorithm/is_permutation.h @@ -12,17 +12,14 @@ #include <__algorithm/comp.h> #include <__config> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> -#include // FIXME: replace with <__iterator/distance.h> when it lands #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -136,15 +133,14 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __fir if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) return false; return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2, - typename add_lvalue_reference<_BinaryPredicate>::type>(__first1, __last1, __first2, - __pred); + _BinaryPredicate&>(__first1, __last1, __first2, __pred); } template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) { - return _VSTD::__is_permutation::type>( + return _VSTD::__is_permutation<_BinaryPredicate&>( __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), typename iterator_traits<_ForwardIterator2>::iterator_category()); } @@ -163,6 +159,4 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt _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 30d8da0499..57953295a8 100644 --- a/lib/libcxx/include/__algorithm/is_sorted.h +++ b/lib/libcxx/include/__algorithm/is_sorted.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_IS_SORTED_H #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> #include <__algorithm/is_sorted_until.h> #include <__config> #include <__iterator/iterator_traits.h> @@ -18,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -29,7 +27,8 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - return _VSTD::is_sorted_until(__first, __last, __comp) == __last; + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__is_sorted_until<_Comp_ref>(__first, __last, __comp) == __last; } template @@ -43,6 +42,4 @@ is_sorted(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_IS_SORTED_H diff --git a/lib/libcxx/include/__algorithm/is_sorted_until.h b/lib/libcxx/include/__algorithm/is_sorted_until.h index a914b5a566..57cad47761 100644 --- a/lib/libcxx/include/__algorithm/is_sorted_until.h +++ b/lib/libcxx/include/__algorithm/is_sorted_until.h @@ -9,22 +9,20 @@ #ifndef _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H #define _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +__is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { if (__first != __last) { @@ -39,10 +37,16 @@ is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __co return __last; } +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__is_sorted_until<_Comp_ref>(__first, __last, __comp); +} + template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { return _VSTD::is_sorted_until(__first, __last, __less::value_type>()); @@ -50,6 +54,4 @@ is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H diff --git a/lib/libcxx/include/__algorithm/iter_swap.h b/lib/libcxx/include/__algorithm/iter_swap.h index b63bce62cc..9f7d0d7763 100644 --- a/lib/libcxx/include/__algorithm/iter_swap.h +++ b/lib/libcxx/include/__algorithm/iter_swap.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void iter_swap(_F _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_ITER_SWAP_H diff --git a/lib/libcxx/include/__algorithm/lexicographical_compare.h b/lib/libcxx/include/__algorithm/lexicographical_compare.h index 6e4a90bdc0..55a1da6201 100644 --- a/lib/libcxx/include/__algorithm/lexicographical_compare.h +++ b/lib/libcxx/include/__algorithm/lexicographical_compare.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H #define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -63,6 +60,4 @@ lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H diff --git a/lib/libcxx/include/__algorithm/lower_bound.h b/lib/libcxx/include/__algorithm/lower_bound.h index 1448c89633..663a0b1622 100644 --- a/lib/libcxx/include/__algorithm/lower_bound.h +++ b/lib/libcxx/include/__algorithm/lower_bound.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_LOWER_BOUND_H #define _LIBCPP___ALGORITHM_LOWER_BOUND_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/half_positive.h> +#include <__config> #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 @@ -51,8 +48,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) { - typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; - return _VSTD::__lower_bound<_Comp_ref>(__first, __last, __value_, __comp); + return _VSTD::__lower_bound<_Compare&>(__first, __last, __value_, __comp); } template @@ -67,6 +63,4 @@ lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_LOWER_BOUND_H diff --git a/lib/libcxx/include/__algorithm/make_heap.h b/lib/libcxx/include/__algorithm/make_heap.h index eca4013cbd..f489addaf5 100644 --- a/lib/libcxx/include/__algorithm/make_heap.h +++ b/lib/libcxx/include/__algorithm/make_heap.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_MAKE_HEAP_H #define _LIBCPP___ALGORITHM_MAKE_HEAP_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/sift_down.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -35,7 +32,7 @@ __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compar // start from the first parent, there is no need to consider children for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { - _VSTD::__sift_down<_Compare>(__first, __last, __comp, __n, __first + __start); + _VSTD::__sift_down<_Compare>(__first, __comp, __n, __first + __start); } } } @@ -59,6 +56,4 @@ make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H diff --git a/lib/libcxx/include/__algorithm/max.h b/lib/libcxx/include/__algorithm/max.h index 2fa97cad87..0bbc971e0a 100644 --- a/lib/libcxx/include/__algorithm/max.h +++ b/lib/libcxx/include/__algorithm/max.h @@ -9,9 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_MAX_H #define _LIBCPP___ALGORITHM_MAX_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> #include <__algorithm/max_element.h> +#include <__config> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -49,7 +50,8 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Tp max(initializer_list<_Tp> __t, _Compare __comp) { - return *_VSTD::max_element(__t.begin(), __t.end(), __comp); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return *_VSTD::__max_element<_Comp_ref>(__t.begin(), __t.end(), __comp); } template diff --git a/lib/libcxx/include/__algorithm/max_element.h b/lib/libcxx/include/__algorithm/max_element.h index b93b67eacf..db29372605 100644 --- a/lib/libcxx/include/__algorithm/max_element.h +++ b/lib/libcxx/include/__algorithm/max_element.h @@ -9,24 +9,20 @@ #ifndef _LIBCPP___ALGORITHM_MAX_ELEMENT_H #define _LIBCPP___ALGORITHM_MAX_ELEMENT_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -_ForwardIterator -max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator +__max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, "std::max_element requires a ForwardIterator"); @@ -40,11 +36,17 @@ max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) return __first; } +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator +max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__max_element<_Comp_ref>(__first, __last, __comp); +} + template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -_ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { return _VSTD::max_element(__first, __last, @@ -53,6 +55,4 @@ max_element(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MAX_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/merge.h b/lib/libcxx/include/__algorithm/merge.h index ea53ad68f7..9182649377 100644 --- a/lib/libcxx/include/__algorithm/merge.h +++ b/lib/libcxx/include/__algorithm/merge.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_MERGE_H #define _LIBCPP___ALGORITHM_MERGE_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -71,6 +68,4 @@ merge(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MERGE_H diff --git a/lib/libcxx/include/__algorithm/min.h b/lib/libcxx/include/__algorithm/min.h index 9fea7f70a2..ed2d3b8782 100644 --- a/lib/libcxx/include/__algorithm/min.h +++ b/lib/libcxx/include/__algorithm/min.h @@ -9,9 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_MIN_H #define _LIBCPP___ALGORITHM_MIN_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> #include <__algorithm/min_element.h> +#include <__config> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -49,7 +50,8 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Tp min(initializer_list<_Tp> __t, _Compare __comp) { - return *_VSTD::min_element(__t.begin(), __t.end(), __comp); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return *_VSTD::__min_element<_Comp_ref>(__t.begin(), __t.end(), __comp); } template diff --git a/lib/libcxx/include/__algorithm/min_element.h b/lib/libcxx/include/__algorithm/min_element.h index 6bff140e5d..407c7f9333 100644 --- a/lib/libcxx/include/__algorithm/min_element.h +++ b/lib/libcxx/include/__algorithm/min_element.h @@ -9,24 +9,20 @@ #ifndef _LIBCPP___ALGORITHM_MIN_ELEMENT_H #define _LIBCPP___ALGORITHM_MIN_ELEMENT_H -#include <__config> #include <__algorithm/comp.h> +#include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -_ForwardIterator -min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator +__min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); @@ -40,10 +36,16 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) return __first; } +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator +min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) +{ + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + return _VSTD::__min_element<_Comp_ref>(__first, __last, __comp); +} + template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -_ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { return _VSTD::min_element(__first, __last, @@ -52,6 +54,4 @@ min_element(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/minmax.h b/lib/libcxx/include/__algorithm/minmax.h index 63753f2fec..0bf88a70b8 100644 --- a/lib/libcxx/include/__algorithm/minmax.h +++ b/lib/libcxx/include/__algorithm/minmax.h @@ -9,19 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_MINMAX_H #define _LIBCPP___ALGORITHM_MINMAX_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #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 @@ -96,6 +92,4 @@ minmax(initializer_list<_Tp> __t) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MINMAX_H diff --git a/lib/libcxx/include/__algorithm/minmax_element.h b/lib/libcxx/include/__algorithm/minmax_element.h index 1eba006de9..5d76860384 100644 --- a/lib/libcxx/include/__algorithm/minmax_element.h +++ b/lib/libcxx/include/__algorithm/minmax_element.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H #define _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.h> #include @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -85,6 +82,4 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/mismatch.h b/lib/libcxx/include/__algorithm/mismatch.h index fdd2bc8c09..230ade03df 100644 --- a/lib/libcxx/include/__algorithm/mismatch.h +++ b/lib/libcxx/include/__algorithm/mismatch.h @@ -10,8 +10,8 @@ #ifndef _LIBCPP___ALGORITHM_MISMATCH_H #define _LIBCPP___ALGORITHM_MISMATCH_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.h> #include @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -67,6 +64,4 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MISMATCH_H diff --git a/lib/libcxx/include/__algorithm/move.h b/lib/libcxx/include/__algorithm/move.h index f5fc74854f..fa118f4716 100644 --- a/lib/libcxx/include/__algorithm/move.h +++ b/lib/libcxx/include/__algorithm/move.h @@ -9,20 +9,17 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_H #define _LIBCPP___ALGORITHM_MOVE_H -#include <__config> #include <__algorithm/unwrap_iter.h> +#include <__config> #include <__utility/move.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 // move @@ -78,6 +75,4 @@ move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MOVE_H diff --git a/lib/libcxx/include/__algorithm/move_backward.h b/lib/libcxx/include/__algorithm/move_backward.h index 1c93b98197..a4e3828b60 100644 --- a/lib/libcxx/include/__algorithm/move_backward.h +++ b/lib/libcxx/include/__algorithm/move_backward.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H -#include <__config> #include <__algorithm/unwrap_iter.h> +#include <__config> #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 template @@ -79,6 +76,4 @@ move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H diff --git a/lib/libcxx/include/__algorithm/next_permutation.h b/lib/libcxx/include/__algorithm/next_permutation.h index a337e5efa0..eb81cceb7b 100644 --- a/lib/libcxx/include/__algorithm/next_permutation.h +++ b/lib/libcxx/include/__algorithm/next_permutation.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H #define _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/reverse.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -72,6 +69,4 @@ next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/none_of.h b/lib/libcxx/include/__algorithm/none_of.h index 285691520c..10339e2418 100644 --- a/lib/libcxx/include/__algorithm/none_of.h +++ b/lib/libcxx/include/__algorithm/none_of.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_NONE_OF_H diff --git a/lib/libcxx/include/__algorithm/nth_element.h b/lib/libcxx/include/__algorithm/nth_element.h index 67a03cfc37..3afbd6c618 100644 --- a/lib/libcxx/include/__algorithm/nth_element.h +++ b/lib/libcxx/include/__algorithm/nth_element.h @@ -9,20 +9,21 @@ #ifndef _LIBCPP___ALGORITHM_NTH_ELEMENT_H #define _LIBCPP___ALGORITHM_NTH_ELEMENT_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/sort.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> +#if defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) +# include <__algorithm/shuffle.h> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -225,8 +226,13 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - _VSTD::__nth_element<_Comp_ref>(__first, __nth, __last, __comp); + _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + _VSTD::__nth_element<_Comp_ref>(__first, __nth, __last, __comp); + _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __nth); + if (__nth != __last) { + _LIBCPP_DEBUG_RANDOMIZE_RANGE(++__nth, __last); + } } template @@ -239,6 +245,4 @@ nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomA _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H diff --git a/lib/libcxx/include/__algorithm/partial_sort.h b/lib/libcxx/include/__algorithm/partial_sort.h index 4f9872c492..a92a7e5661 100644 --- a/lib/libcxx/include/__algorithm/partial_sort.h +++ b/lib/libcxx/include/__algorithm/partial_sort.h @@ -9,29 +9,32 @@ #ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_H #define _LIBCPP___ALGORITHM_PARTIAL_SORT_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/make_heap.h> #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> +#if defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) +# include <__algorithm/shuffle.h> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_CONSTEXPR_AFTER_CXX17 void __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, - _Compare __comp) + _Compare __comp) { + if (__first == __middle) + return; _VSTD::__make_heap<_Compare>(__first, __middle, __comp); typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; for (_RandomAccessIterator __i = __middle; __i != __last; ++__i) @@ -39,7 +42,7 @@ __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _R if (__comp(*__i, *__first)) { swap(*__i, *__first); - _VSTD::__sift_down<_Compare>(__first, __middle, __comp, __len, __first); + _VSTD::__sift_down<_Compare>(__first, __comp, __len, __first); } } _VSTD::__sort_heap<_Compare>(__first, __middle, __comp); @@ -51,8 +54,10 @@ void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - _VSTD::__partial_sort<_Comp_ref>(__first, __middle, __last, __comp); + _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + _VSTD::__partial_sort<_Comp_ref>(__first, __middle, __last, __comp); + _LIBCPP_DEBUG_RANDOMIZE_RANGE(__middle, __last); } template @@ -61,11 +66,9 @@ void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { _VSTD::partial_sort(__first, __middle, __last, - __less::value_type>()); + __less::value_type>()); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H diff --git a/lib/libcxx/include/__algorithm/partial_sort_copy.h b/lib/libcxx/include/__algorithm/partial_sort_copy.h index 31a12615fa..67a62bae1f 100644 --- a/lib/libcxx/include/__algorithm/partial_sort_copy.h +++ b/lib/libcxx/include/__algorithm/partial_sort_copy.h @@ -9,22 +9,18 @@ #ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H #define _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/make_heap.h> #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> +#include <__config> #include <__iterator/iterator_traits.h> -#include // swap #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -43,7 +39,7 @@ __partial_sort_copy(_InputIterator __first, _InputIterator __last, if (__comp(*__first, *__result_first)) { *__result_first = *__first; - _VSTD::__sift_down<_Compare>(__result_first, __r, __comp, __len, __result_first); + _VSTD::__sift_down<_Compare>(__result_first, __comp, __len, __result_first); } _VSTD::__sort_heap<_Compare>(__result_first, __r, __comp); } @@ -72,6 +68,4 @@ partial_sort_copy(_InputIterator __first, _InputIterator __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H diff --git a/lib/libcxx/include/__algorithm/partition.h b/lib/libcxx/include/__algorithm/partition.h index c859eaca28..131c5d3735 100644 --- a/lib/libcxx/include/__algorithm/partition.h +++ b/lib/libcxx/include/__algorithm/partition.h @@ -12,16 +12,11 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> -#include // pair -#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 @@ -77,12 +72,10 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return _VSTD::__partition::type> - (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); + return _VSTD::__partition<_Predicate&>( + __first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PARTITION_H diff --git a/lib/libcxx/include/__algorithm/partition_copy.h b/lib/libcxx/include/__algorithm/partition_copy.h index 445eacdfbe..d34944589b 100644 --- a/lib/libcxx/include/__algorithm/partition_copy.h +++ b/lib/libcxx/include/__algorithm/partition_copy.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template #include <__algorithm/half_positive.h> +#include <__config> #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 @@ -46,6 +43,4 @@ partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __ _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PARTITION_POINT_H diff --git a/lib/libcxx/include/__algorithm/pop_heap.h b/lib/libcxx/include/__algorithm/pop_heap.h index 7ebbef25e0..c1cc8016ac 100644 --- a/lib/libcxx/include/__algorithm/pop_heap.h +++ b/lib/libcxx/include/__algorithm/pop_heap.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_POP_HEAP_H #define _LIBCPP___ALGORITHM_POP_HEAP_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/sift_down.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -34,7 +31,7 @@ __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare if (__len > 1) { swap(*__first, *--__last); - _VSTD::__sift_down<_Compare>(__first, __last, __comp, __len - 1, __first); + _VSTD::__sift_down<_Compare>(__first, __comp, __len - 1, __first); } } @@ -57,6 +54,4 @@ pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) _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 d6daa73ada..457c2695b3 100644 --- a/lib/libcxx/include/__algorithm/prev_permutation.h +++ b/lib/libcxx/include/__algorithm/prev_permutation.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_PREV_PERMUTATION_H #define _LIBCPP___ALGORITHM_PREV_PERMUTATION_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/reverse.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -72,6 +69,4 @@ prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PREV_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/push_heap.h b/lib/libcxx/include/__algorithm/push_heap.h index 82a7c123d8..864d419fa2 100644 --- a/lib/libcxx/include/__algorithm/push_heap.h +++ b/lib/libcxx/include/__algorithm/push_heap.h @@ -9,9 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_PUSH_HEAP_H #define _LIBCPP___ALGORITHM_PUSH_HEAP_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -70,6 +67,4 @@ push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_PUSH_HEAP_H diff --git a/lib/libcxx/include/__algorithm/remove.h b/lib/libcxx/include/__algorithm/remove.h index 4717d7d973..681b9cc768 100644 --- a/lib/libcxx/include/__algorithm/remove.h +++ b/lib/libcxx/include/__algorithm/remove.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_REMOVE_H #define _LIBCPP___ALGORITHM_REMOVE_H -#include <__config> #include <__algorithm/find.h> #include <__algorithm/find_if.h> +#include <__config> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -45,6 +42,4 @@ remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REMOVE_H diff --git a/lib/libcxx/include/__algorithm/remove_copy.h b/lib/libcxx/include/__algorithm/remove_copy.h index 5d2b640343..338ca94300 100644 --- a/lib/libcxx/include/__algorithm/remove_copy.h +++ b/lib/libcxx/include/__algorithm/remove_copy.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -38,6 +35,4 @@ remove_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __res _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REMOVE_COPY_H diff --git a/lib/libcxx/include/__algorithm/remove_copy_if.h b/lib/libcxx/include/__algorithm/remove_copy_if.h index 44822564a5..a556387220 100644 --- a/lib/libcxx/include/__algorithm/remove_copy_if.h +++ b/lib/libcxx/include/__algorithm/remove_copy_if.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -38,6 +35,4 @@ remove_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __ _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/remove_if.h b/lib/libcxx/include/__algorithm/remove_if.h index e506b4c67f..36f817cfa6 100644 --- a/lib/libcxx/include/__algorithm/remove_if.h +++ b/lib/libcxx/include/__algorithm/remove_if.h @@ -9,26 +9,21 @@ #ifndef _LIBCPP___ALGORITHM_REMOVE_IF_H #define _LIBCPP___ALGORITHM_REMOVE_IF_H -#include <__config> #include <__algorithm/find_if.h> +#include <__config> #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 _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - __first = _VSTD::find_if<_ForwardIterator, typename add_lvalue_reference<_Predicate>::type> - (__first, __last, __pred); + __first = _VSTD::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred); if (__first != __last) { _ForwardIterator __i = __first; @@ -46,6 +41,4 @@ remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REMOVE_IF_H diff --git a/lib/libcxx/include/__algorithm/replace.h b/lib/libcxx/include/__algorithm/replace.h index b723ffeeac..2bc96ffc87 100644 --- a/lib/libcxx/include/__algorithm/replace.h +++ b/lib/libcxx/include/__algorithm/replace.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_valu _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REPLACE_H diff --git a/lib/libcxx/include/__algorithm/replace_copy.h b/lib/libcxx/include/__algorithm/replace_copy.h index 1923a57e42..c6c5fe32e8 100644 --- a/lib/libcxx/include/__algorithm/replace_copy.h +++ b/lib/libcxx/include/__algorithm/replace_copy.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -36,6 +33,4 @@ replace_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __re _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REPLACE_COPY_H diff --git a/lib/libcxx/include/__algorithm/replace_copy_if.h b/lib/libcxx/include/__algorithm/replace_copy_if.h index 72b6f73697..274d8e630e 100644 --- a/lib/libcxx/include/__algorithm/replace_copy_if.h +++ b/lib/libcxx/include/__algorithm/replace_copy_if.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -36,6 +33,4 @@ replace_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator _ _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H diff --git a/lib/libcxx/include/__algorithm/replace_if.h b/lib/libcxx/include/__algorithm/replace_if.h index 49101a5ce1..bcc3feb2f5 100644 --- a/lib/libcxx/include/__algorithm/replace_if.h +++ b/lib/libcxx/include/__algorithm/replace_if.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REPLACE_IF_H diff --git a/lib/libcxx/include/__algorithm/reverse.h b/lib/libcxx/include/__algorithm/reverse.h index e538de1147..1198aeaf41 100644 --- a/lib/libcxx/include/__algorithm/reverse.h +++ b/lib/libcxx/include/__algorithm/reverse.h @@ -9,17 +9,14 @@ #ifndef _LIBCPP___ALGORITHM_REVERSE_H #define _LIBCPP___ALGORITHM_REVERSE_H -#include <__config> #include <__algorithm/iter_swap.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -56,6 +53,4 @@ reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REVERSE_H diff --git a/lib/libcxx/include/__algorithm/reverse_copy.h b/lib/libcxx/include/__algorithm/reverse_copy.h index 48ce60cf88..002c0344a7 100644 --- a/lib/libcxx/include/__algorithm/reverse_copy.h +++ b/lib/libcxx/include/__algorithm/reverse_copy.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _Out _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_REVERSE_COPY_H diff --git a/lib/libcxx/include/__algorithm/rotate.h b/lib/libcxx/include/__algorithm/rotate.h index 0c9ccd7bf7..fd6d3e9c11 100644 --- a/lib/libcxx/include/__algorithm/rotate.h +++ b/lib/libcxx/include/__algorithm/rotate.h @@ -23,9 +23,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -200,6 +197,4 @@ rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __l _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_ROTATE_H diff --git a/lib/libcxx/include/__algorithm/rotate_copy.h b/lib/libcxx/include/__algorithm/rotate_copy.h index d5ab7d3b51..f9e644c88d 100644 --- a/lib/libcxx/include/__algorithm/rotate_copy.h +++ b/lib/libcxx/include/__algorithm/rotate_copy.h @@ -9,18 +9,13 @@ #ifndef _LIBCPP___ALGORITHM_ROTATE_COPY_H #define _LIBCPP___ALGORITHM_ROTATE_COPY_H -#include <__config> #include <__algorithm/copy.h> -#include -#include +#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 template @@ -33,6 +28,4 @@ rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterato _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_ROTATE_COPY_H diff --git a/lib/libcxx/include/__algorithm/sample.h b/lib/libcxx/include/__algorithm/sample.h index 2aac6ffa8c..33264c4ea3 100644 --- a/lib/libcxx/include/__algorithm/sample.h +++ b/lib/libcxx/include/__algorithm/sample.h @@ -9,8 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_SAMPLE_H #define _LIBCPP___ALGORITHM_SAMPLE_H -#include <__config> #include <__algorithm/min.h> +#include <__config> +#include <__debug> #include <__random/uniform_int_distribution.h> #include diff --git a/lib/libcxx/include/__algorithm/search.h b/lib/libcxx/include/__algorithm/search.h index 008b8ebb04..cfaec0ed1e 100644 --- a/lib/libcxx/include/__algorithm/search.h +++ b/lib/libcxx/include/__algorithm/search.h @@ -13,16 +13,12 @@ #include <__algorithm/comp.h> #include <__config> #include <__iterator/iterator_traits.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 @@ -72,7 +68,7 @@ __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _Rando const _D1 __len1 = __last1 - __first1; if (__len1 < __len2) return _VSTD::make_pair(__last1, __last1); - const _RandomAccessIterator1 __s = __last1 - (__len2 - 1); // Start of pattern match can't go beyond here + const _RandomAccessIterator1 __s = __last1 - _D1(__len2 - 1); // Start of pattern match can't go beyond here while (true) { while (true) { @@ -87,7 +83,7 @@ __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _Rando _RandomAccessIterator2 __m2 = __first2; while (true) { if (++__m2 == __last2) - return _VSTD::make_pair(__first1, __first1 + __len2); + return _VSTD::make_pair(__first1, __first1 + _D1(__len2)); ++__m1; // no need to check range on __m1 because __s guarantees we have enough source if (!__pred(*__m1, *__m2)) { ++__first1; @@ -101,7 +97,7 @@ template ::type>( + return _VSTD::__search<_BinaryPredicate&>( __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), typename iterator_traits<_ForwardIterator2>::iterator_category()).first; @@ -126,6 +122,4 @@ search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SEARCH_H diff --git a/lib/libcxx/include/__algorithm/search_n.h b/lib/libcxx/include/__algorithm/search_n.h index 1584e8e613..e4576cc76a 100644 --- a/lib/libcxx/include/__algorithm/search_n.h +++ b/lib/libcxx/include/__algorithm/search_n.h @@ -10,18 +10,15 @@ #ifndef _LIBCPP___ALGORITHM_SEARCH_N_H #define _LIBCPP___ALGORITHM_SEARCH_N_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.h> -#include +#include // __convert_to_integral #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -62,12 +59,13 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator __search_n(_RandomAccessIter _RandomAccessIterator __last, _Size __count, const _Tp& __value_, _BinaryPredicate __pred, random_access_iterator_tag) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; if (__count <= 0) return __first; _Size __len = static_cast<_Size>(__last - __first); if (__len < __count) return __last; - const _RandomAccessIterator __s = __last - (__count - 1); // Start of pattern match can't go beyond here + const _RandomAccessIterator __s = __last - difference_type(__count - 1); // Start of pattern match can't go beyond here while (true) { // Find first element in sequence that matchs __value_, with a mininum of loop checks while (true) { @@ -97,7 +95,7 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator __search_n(_RandomAccessIter template _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator search_n( _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_, _BinaryPredicate __pred) { - return _VSTD::__search_n::type>( + return _VSTD::__search_n<_BinaryPredicate&>( __first, __last, _VSTD::__convert_to_integral(__count), __value_, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); } @@ -111,6 +109,4 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SEARCH_N_H diff --git a/lib/libcxx/include/__algorithm/set_difference.h b/lib/libcxx/include/__algorithm/set_difference.h index f4c985d978..00f61e070b 100644 --- a/lib/libcxx/include/__algorithm/set_difference.h +++ b/lib/libcxx/include/__algorithm/set_difference.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_SET_DIFFERENCE_H #define _LIBCPP___ALGORITHM_SET_DIFFERENCE_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -72,6 +69,4 @@ set_difference(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SET_DIFFERENCE_H diff --git a/lib/libcxx/include/__algorithm/set_intersection.h b/lib/libcxx/include/__algorithm/set_intersection.h index 9d34b66c23..f6aa38217d 100644 --- a/lib/libcxx/include/__algorithm/set_intersection.h +++ b/lib/libcxx/include/__algorithm/set_intersection.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_SET_INTERSECTION_H #define _LIBCPP___ALGORITHM_SET_INTERSECTION_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -69,6 +66,4 @@ set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SET_INTERSECTION_H diff --git a/lib/libcxx/include/__algorithm/set_symmetric_difference.h b/lib/libcxx/include/__algorithm/set_symmetric_difference.h index 5650b836a6..5b5c2acff7 100644 --- a/lib/libcxx/include/__algorithm/set_symmetric_difference.h +++ b/lib/libcxx/include/__algorithm/set_symmetric_difference.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H #define _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -77,6 +74,4 @@ set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H diff --git a/lib/libcxx/include/__algorithm/set_union.h b/lib/libcxx/include/__algorithm/set_union.h index c0874e9574..5b3e3af79b 100644 --- a/lib/libcxx/include/__algorithm/set_union.h +++ b/lib/libcxx/include/__algorithm/set_union.h @@ -9,19 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_SET_UNION_H #define _LIBCPP___ALGORITHM_SET_UNION_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__config> #include <__iterator/iterator_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -72,6 +69,4 @@ set_union(_InputIterator1 __first1, _InputIterator1 __last1, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SET_UNION_H diff --git a/lib/libcxx/include/__algorithm/shift_left.h b/lib/libcxx/include/__algorithm/shift_left.h index 961b89cb00..0466a3188a 100644 --- a/lib/libcxx/include/__algorithm/shift_left.h +++ b/lib/libcxx/include/__algorithm/shift_left.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_SHIFT_LEFT_H #define _LIBCPP___ALGORITHM_SHIFT_LEFT_H -#include <__config> #include <__algorithm/move.h> +#include <__config> #include <__iterator/iterator_traits.h> -#include // swap +#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 @@ -56,6 +53,4 @@ shift_left(_ForwardIterator __first, _ForwardIterator __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SHIFT_LEFT_H diff --git a/lib/libcxx/include/__algorithm/shift_right.h b/lib/libcxx/include/__algorithm/shift_right.h index 5cb4195064..121712e855 100644 --- a/lib/libcxx/include/__algorithm/shift_right.h +++ b/lib/libcxx/include/__algorithm/shift_right.h @@ -9,20 +9,18 @@ #ifndef _LIBCPP___ALGORITHM_SHIFT_RIGHT_H #define _LIBCPP___ALGORITHM_SHIFT_RIGHT_H -#include <__config> #include <__algorithm/move.h> #include <__algorithm/move_backward.h> #include <__algorithm/swap_ranges.h> +#include <__config> #include <__iterator/iterator_traits.h> -#include // swap +#include <__utility/swap.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 @@ -101,6 +99,4 @@ shift_right(_ForwardIterator __first, _ForwardIterator __last, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SHIFT_RIGHT_H diff --git a/lib/libcxx/include/__algorithm/shuffle.h b/lib/libcxx/include/__algorithm/shuffle.h index 637fca5388..7f6ad50e24 100644 --- a/lib/libcxx/include/__algorithm/shuffle.h +++ b/lib/libcxx/include/__algorithm/shuffle.h @@ -25,6 +25,39 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { +public: + __libcpp_debug_randomizer() { + __state = __seed(); + __inc = __state + 0xda3e39cb94b95bdbULL; + __inc = (__inc << 1) | 1; + } + typedef uint_fast32_t result_type; + + static const result_type _Min = 0; + static const result_type _Max = 0xFFFFFFFF; + + _LIBCPP_HIDE_FROM_ABI result_type operator()() { + uint_fast64_t __oldstate = __state; + __state = __oldstate * 6364136223846793005ULL + __inc; + return __oldstate >> 32; + } + + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } + +private: + uint_fast64_t __state; + uint_fast64_t __inc; + _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { +#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED + return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; +#else + static char __x; + return reinterpret_cast(&__x); +#endif + } +}; #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ || defined(_LIBCPP_BUILDING_LIBRARY) diff --git a/lib/libcxx/include/__algorithm/sift_down.h b/lib/libcxx/include/__algorithm/sift_down.h index dd4b54ed8e..bf5447698c 100644 --- a/lib/libcxx/include/__algorithm/sift_down.h +++ b/lib/libcxx/include/__algorithm/sift_down.h @@ -17,15 +17,11 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_CONSTEXPR_AFTER_CXX11 void -__sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, - _Compare __comp, +__sift_down(_RandomAccessIterator __first, _Compare __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, _RandomAccessIterator __start) { @@ -41,7 +37,7 @@ __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, __child = 2 * __child + 1; _RandomAccessIterator __child_i = __first + __child; - if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { + if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { // right-child exists and is greater than left-child ++__child_i; ++__child; @@ -49,7 +45,7 @@ __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, // check if we are in heap-order if (__comp(*__child_i, *__start)) - // we are, __start is larger than it's largest child + // we are, __start is larger than its largest child return; value_type __top(_VSTD::move(*__start)); @@ -66,7 +62,7 @@ __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, __child = 2 * __child + 1; __child_i = __first + __child; - if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { + if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { // right-child exists and is greater than left-child ++__child_i; ++__child; @@ -79,6 +75,4 @@ __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, _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 39ec21302d..5e09b28008 100644 --- a/lib/libcxx/include/__algorithm/sort.h +++ b/lib/libcxx/include/__algorithm/sort.h @@ -9,23 +9,23 @@ #ifndef _LIBCPP___ALGORITHM_SORT_H #define _LIBCPP___ALGORITHM_SORT_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/min_element.h> #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> +#include <__config> #include <__utility/swap.h> #include -#include // swap + +#if defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) +# include <__algorithm/shuffle.h> +#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD // stable, 2-3 compares, 0-2 swaps @@ -131,9 +131,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __lm1 = __last; for (--__lm1; __first != __lm1; ++__first) { - _BidirectionalIterator __i = _VSTD::min_element<_BidirectionalIterator, - typename add_lvalue_reference<_Compare>::type> - (__first, __last, __comp); + _BidirectionalIterator __i = _VSTD::min_element(__first, __last, __comp); if (__i != __first) swap(*__first, *__i); } @@ -162,10 +160,11 @@ template void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; - _RandomAccessIterator __j = __first+2; - _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); - for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) + _RandomAccessIterator __j = __first+difference_type(2); + _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), __j, __comp); + for (_RandomAccessIterator __i = __j+difference_type(1); __i != __last; ++__i) { if (__comp(*__i, *__j)) { @@ -187,6 +186,7 @@ template bool __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; switch (__last - __first) { case 0: @@ -197,21 +197,21 @@ __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator swap(*__first, *__last); return true; case 3: - _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); + _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), --__last, __comp); return true; case 4: - _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); + _VSTD::__sort4<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), --__last, __comp); return true; case 5: - _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); + _VSTD::__sort5<_Compare>(__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+2; - _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); + _RandomAccessIterator __j = __first+difference_type(2); + _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), __j, __comp); const unsigned __limit = 8; unsigned __count = 0; - for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) + for (_RandomAccessIterator __i = __j+difference_type(1); __i != __last; ++__i) { if (__comp(*__i, *__j)) { @@ -269,7 +269,8 @@ __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __ template void -__sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) +__introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, + typename iterator_traits<_RandomAccessIterator>::difference_type __depth) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; @@ -289,13 +290,13 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c swap(*__first, *__last); return; case 3: - _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); + _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), --__last, __comp); return; case 4: - _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); + _VSTD::__sort4<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), --__last, __comp); return; case 5: - _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); + _VSTD::__sort5<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), __first+difference_type(3), --__last, __comp); return; } if (__len <= __limit) @@ -304,6 +305,13 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c return; } // __len > 5 + if (__depth == 0) + { + // Fallback to heap sort as Introsort suggests. + _VSTD::__partial_sort<_Compare>(__first, __last, __last, __comp); + return; + } + --__depth; _RandomAccessIterator __m = __first; _RandomAccessIterator __lm1 = __last; --__lm1; @@ -427,7 +435,7 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c if (__n_swaps == 0) { bool __fs = _VSTD::__insertion_sort_incomplete<_Compare>(__first, __i, __comp); - if (_VSTD::__insertion_sort_incomplete<_Compare>(__i+1, __last, __comp)) + if (_VSTD::__insertion_sort_incomplete<_Compare>(__i+difference_type(1), __last, __comp)) { if (__fs) return; @@ -446,19 +454,34 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c // sort smaller range with recursive call and larger with tail recursion elimination if (__i - __first < __last - __i) { - _VSTD::__sort<_Compare>(__first, __i, __comp); - // _VSTD::__sort<_Compare>(__i+1, __last, __comp); - __first = ++__i; + _VSTD::__introsort<_Compare>(__first, __i, __comp, __depth); + __first = ++__i; } else { - _VSTD::__sort<_Compare>(__i+1, __last, __comp); - // _VSTD::__sort<_Compare>(__first, __i, __comp); - __last = __i; + _VSTD::__introsort<_Compare>(__i + difference_type(1), __last, __comp, __depth); + __last = __i; } } } +template +inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { + _Number __log2 = 0; + while (__n > 1) { + __log2++; + __n >>= 1; + } + return __log2; +} + +template +void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; + difference_type __depth_limit = 2 * __log2i(__last - __first); + _VSTD::__introsort<_Compare>(__first, __last, __comp, __depth_limit); +} + template inline _LIBCPP_INLINE_VISIBILITY void @@ -469,7 +492,9 @@ __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) } _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, char*>(char*, char*, __less&)) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&)) +#endif _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, signed char*>(signed char*, signed char*, __less&)) _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&)) _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, short*>(short*, short*, __less&)) @@ -485,7 +510,9 @@ _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, double*>(d _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less&, long double*>(long double*, long double*, __less&)) _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, char*>(char*, char*, __less&)) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, wchar_t*>(wchar_t*, wchar_t*, __less&)) +#endif _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, signed char*>(signed char*, signed char*, __less&)) _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, unsigned char*>(unsigned char*, unsigned char*, __less&)) _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less&, short*>(short*, short*, __less&)) @@ -507,12 +534,13 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - if (__libcpp_is_constant_evaluated()) { - _VSTD::__partial_sort<_Comp_ref>(__first, __last, __last, _Comp_ref(__comp)); - } else { - _VSTD::__sort<_Comp_ref>(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _Comp_ref(__comp)); - } + _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last); + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + if (__libcpp_is_constant_evaluated()) { + _VSTD::__partial_sort<_Comp_ref>(__first, __last, __last, _Comp_ref(__comp)); + } else { + _VSTD::__sort<_Comp_ref>(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _Comp_ref(__comp)); + } } template @@ -525,6 +553,4 @@ sort(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SORT_H diff --git a/lib/libcxx/include/__algorithm/sort_heap.h b/lib/libcxx/include/__algorithm/sort_heap.h index aa8ef762ab..64291ff2e8 100644 --- a/lib/libcxx/include/__algorithm/sort_heap.h +++ b/lib/libcxx/include/__algorithm/sort_heap.h @@ -9,10 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_SORT_HEAP_H #define _LIBCPP___ALGORITHM_SORT_HEAP_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/pop_heap.h> +#include <__config> #include <__iterator/iterator_traits.h> #include // swap @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -53,6 +50,4 @@ sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SORT_HEAP_H diff --git a/lib/libcxx/include/__algorithm/stable_partition.h b/lib/libcxx/include/__algorithm/stable_partition.h index 931335f444..331f0fde77 100644 --- a/lib/libcxx/include/__algorithm/stable_partition.h +++ b/lib/libcxx/include/__algorithm/stable_partition.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H -#include <__config> #include <__algorithm/rotate.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> #include @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -85,8 +82,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate // recurse on [__first, __m), *__first know to be false // F????????????????? // f m l - typedef typename add_lvalue_reference<_Predicate>::type _PredRef; - _ForwardIterator __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m, __pred, __len2, __p, __fit); + _ForwardIterator __first_false = _VSTD::__stable_partition<_Predicate&>(__first, __m, __pred, __len2, __p, __fit); // TTTFFFFF?????????? // f ff m l // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true @@ -101,7 +97,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate } // TTTFFFFFTTTF?????? // f ff m m1 l - __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __fit); + __second_false = _VSTD::__stable_partition<_Predicate&>(__m1, __last, __pred, __len_half, __p, __fit); __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l @@ -137,8 +133,7 @@ __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __p = _VSTD::get_temporary_buffer(__len); __h.reset(__p.first); } - return _VSTD::__stable_partition::type> - (__first, __last, __pred, __len, __p, forward_iterator_tag()); + return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, __len, __p, forward_iterator_tag()); } template @@ -222,8 +217,7 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last } // F???TFFF?????????T // f m1 m l - typedef typename add_lvalue_reference<_Predicate>::type _PredRef; - __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m1, __pred, __len_half, __p, __bit); + __first_false = _VSTD::__stable_partition<_Predicate&>(__first, __m1, __pred, __len_half, __p, __bit); __first_half_done: // TTTFFFFF?????????T // f ff m l @@ -240,7 +234,7 @@ __first_half_done: } // TTTFFFFFTTTF?????T // f ff m m1 l - __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __bit); + __second_false = _VSTD::__stable_partition<_Predicate&>(__m1, __last, __pred, __len_half, __p, __bit); __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l @@ -285,8 +279,7 @@ __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last __p = _VSTD::get_temporary_buffer(__len); __h.reset(__p.first); } - return _VSTD::__stable_partition::type> - (__first, __last, __pred, __len, __p, bidirectional_iterator_tag()); + return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, __len, __p, bidirectional_iterator_tag()); } template @@ -294,12 +287,9 @@ inline _LIBCPP_INLINE_VISIBILITY _ForwardIterator stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return _VSTD::__stable_partition::type> - (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); + return _VSTD::__stable_partition<_Predicate&>(__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H diff --git a/lib/libcxx/include/__algorithm/stable_sort.h b/lib/libcxx/include/__algorithm/stable_sort.h index 32b239a0d7..4ae17e0e4d 100644 --- a/lib/libcxx/include/__algorithm/stable_sort.h +++ b/lib/libcxx/include/__algorithm/stable_sort.h @@ -9,23 +9,20 @@ #ifndef _LIBCPP___ALGORITHM_STABLE_SORT_H #define _LIBCPP___ALGORITHM_STABLE_SORT_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/inplace_merge.h> #include <__algorithm/sort.h> +#include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> #include -#include // swap +#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 @@ -41,14 +38,14 @@ __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, { if (__first1 == __last1) { - for (; __first2 != __last2; ++__first2, ++__result, (void)__d.template __incr()) + for (; __first2 != __last2; ++__first2, (void) ++__result, __d.template __incr()) ::new ((void*)__result) value_type(_VSTD::move(*__first2)); __h.release(); return; } if (__first2 == __last2) { - for (; __first1 != __last1; ++__first1, ++__result, (void)__d.template __incr()) + for (; __first1 != __last1; ++__first1, (void) ++__result, __d.template __incr()) ::new ((void*)__result) value_type(_VSTD::move(*__first1)); __h.release(); return; @@ -230,6 +227,4 @@ stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_STABLE_SORT_H diff --git a/lib/libcxx/include/__algorithm/swap_ranges.h b/lib/libcxx/include/__algorithm/swap_ranges.h index 3c72dbd24c..2b099c7361 100644 --- a/lib/libcxx/include/__algorithm/swap_ranges.h +++ b/lib/libcxx/include/__algorithm/swap_ranges.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -32,6 +29,4 @@ swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardItera _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_SWAP_RANGES_H diff --git a/lib/libcxx/include/__algorithm/transform.h b/lib/libcxx/include/__algorithm/transform.h index 218f0f12ea..494cb7128d 100644 --- a/lib/libcxx/include/__algorithm/transform.h +++ b/lib/libcxx/include/__algorithm/transform.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -43,6 +40,4 @@ transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __f _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_TRANSFORM_H diff --git a/lib/libcxx/include/__algorithm/unique.h b/lib/libcxx/include/__algorithm/unique.h index fb6251a39a..e17ff1567f 100644 --- a/lib/libcxx/include/__algorithm/unique.h +++ b/lib/libcxx/include/__algorithm/unique.h @@ -9,20 +9,16 @@ #ifndef _LIBCPP___ALGORITHM_UNIQUE_H #define _LIBCPP___ALGORITHM_UNIQUE_H -#include <__config> -#include <__algorithm/comp.h> #include <__algorithm/adjacent_find.h> +#include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.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 // unique @@ -31,8 +27,7 @@ template _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - __first = _VSTD::adjacent_find<_ForwardIterator, typename add_lvalue_reference<_BinaryPredicate>::type> - (__first, __last, __pred); + __first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred); if (__first != __last) { // ... a a ? ... @@ -58,6 +53,4 @@ unique(_ForwardIterator __first, _ForwardIterator __last) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_UNIQUE_H diff --git a/lib/libcxx/include/__algorithm/unique_copy.h b/lib/libcxx/include/__algorithm/unique_copy.h index 974a7c4df2..4833ae9b59 100644 --- a/lib/libcxx/include/__algorithm/unique_copy.h +++ b/lib/libcxx/include/__algorithm/unique_copy.h @@ -9,19 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_UNIQUE_COPY_H #define _LIBCPP___ALGORITHM_UNIQUE_COPY_H -#include <__config> #include <__algorithm/comp.h> +#include <__config> #include <__iterator/iterator_traits.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 @@ -91,8 +87,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) { - return _VSTD::__unique_copy::type> - (__first, __last, __result, __pred, + return _VSTD::__unique_copy<_BinaryPredicate&>(__first, __last, __result, __pred, typename iterator_traits<_InputIterator>::iterator_category(), typename iterator_traits<_OutputIterator>::iterator_category()); } @@ -109,6 +104,4 @@ unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __res _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H diff --git a/lib/libcxx/include/__algorithm/unwrap_iter.h b/lib/libcxx/include/__algorithm/unwrap_iter.h index a45d45cdd8..35765330bb 100644 --- a/lib/libcxx/include/__algorithm/unwrap_iter.h +++ b/lib/libcxx/include/__algorithm/unwrap_iter.h @@ -10,17 +10,14 @@ #define _LIBCPP___ALGORITHM_UNWRAP_ITER_H #include <__config> -#include #include <__memory/pointer_traits.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 // The job of __unwrap_iter is to lower contiguous iterators (such as @@ -67,12 +64,14 @@ __unwrap_iter(_Iter __i) _NOEXCEPT } template +_LIBCPP_HIDE_FROM_ABI _OrigIter __rewrap_iter(_OrigIter, _OrigIter __result) { return __result; } template +_LIBCPP_HIDE_FROM_ABI _OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result) { // Precondition: __result is reachable from __first @@ -82,6 +81,4 @@ _OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H diff --git a/lib/libcxx/include/__algorithm/upper_bound.h b/lib/libcxx/include/__algorithm/upper_bound.h index 7be607f825..c064f1e35b 100644 --- a/lib/libcxx/include/__algorithm/upper_bound.h +++ b/lib/libcxx/include/__algorithm/upper_bound.h @@ -9,18 +9,15 @@ #ifndef _LIBCPP___ALGORITHM_UPPER_BOUND_H #define _LIBCPP___ALGORITHM_UPPER_BOUND_H -#include <__config> #include <__algorithm/comp.h> #include <__algorithm/half_positive.h> +#include <__config> #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 @@ -51,8 +48,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) { - typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; - return _VSTD::__upper_bound<_Comp_ref>(__first, __last, __value_, __comp); + return _VSTD::__upper_bound<_Compare&>(__first, __last, __value_, __comp); } template @@ -67,6 +63,4 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ALGORITHM_UPPER_BOUND_H diff --git a/lib/libcxx/include/__availability b/lib/libcxx/include/__availability index 13d11950fd..4652a6fd91 100644 --- a/lib/libcxx/include/__availability +++ b/lib/libcxx/include/__availability @@ -129,6 +129,10 @@ // This controls the availability of std::to_chars. # define _LIBCPP_AVAILABILITY_TO_CHARS + // This controls the availability of floating-point std::to_chars functions. + // These overloads were added later than the integer overloads. +# 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). @@ -139,9 +143,9 @@ // # 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. Currently - // P2216 is aiming to be retroactively accepted in C++20. This paper - // contains ABI breaking changes. + // 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 @@ -222,6 +226,9 @@ # define _LIBCPP_AVAILABILITY_TO_CHARS \ _LIBCPP_AVAILABILITY_FILESYSTEM +# define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT \ + __attribute__((unavailable)) + # define _LIBCPP_AVAILABILITY_SYNC \ __attribute__((availability(macosx,strict,introduced=11.0))) \ __attribute__((availability(ios,strict,introduced=14.0))) \ @@ -238,9 +245,9 @@ # endif // This controls the availability of the C++20 format library. - // The library is in development and not ABI stable yet. Currently - // P2216 is aiming to be retroactively accepted in C++20. This paper - // contains ABI breaking changes. + // 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 \ __attribute__((unavailable)) # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format diff --git a/lib/libcxx/include/__utility/__decay_copy.h b/lib/libcxx/include/__bit/bit_cast.h similarity index 56% rename from lib/libcxx/include/__utility/__decay_copy.h rename to lib/libcxx/include/__bit/bit_cast.h index eda8db6a60..6cfe4d7994 100644 --- a/lib/libcxx/include/__utility/__decay_copy.h +++ b/lib/libcxx/include/__bit/bit_cast.h @@ -7,33 +7,32 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___TYPE_TRAITS_DECAY_COPY_H -#define _LIBCPP___TYPE_TRAITS_DECAY_COPY_H +#ifndef _LIBCPP___BIT_BIT_CAST_H +#define _LIBCPP___BIT_BIT_CAST_H #include <__config> -#include <__utility/forward.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_INLINE_VISIBILITY typename decay<_Tp>::type __decay_copy(_Tp&& __t) #if _LIBCPP_STD_VER > 17 - noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp> >) -#endif -{ - return _VSTD::forward<_Tp>(__t); + +template && + is_trivially_copyable_v<_FromType> +>> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI +constexpr _ToType bit_cast(_FromType const& __from) noexcept { + return __builtin_bit_cast(_ToType, __from); } +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___TYPE_TRAITS_DECAY_COPY_H +#endif // _LIBCPP___BIT_BIT_CAST_H diff --git a/lib/libcxx/include/__bit/byteswap.h b/lib/libcxx/include/__bit/byteswap.h new file mode 100644 index 0000000000..970074ed98 --- /dev/null +++ b/lib/libcxx/include/__bit/byteswap.h @@ -0,0 +1,55 @@ +// -*- 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___BIT_BYTESWAP_H +#define _LIBCPP___BIT_BYTESWAP_H + +#include <__concepts/arithmetic.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 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { + + if constexpr (sizeof(_Tp) == 1) { + return __val; + } else if constexpr (sizeof(_Tp) == 2) { + return __builtin_bswap16(__val); + } else if constexpr (sizeof(_Tp) == 4) { + return __builtin_bswap32(__val); + } else if constexpr (sizeof(_Tp) == 8) { + return __builtin_bswap64(__val); +#ifndef _LIBCPP_HAS_NO_INT128 + } else if constexpr (sizeof(_Tp) == 16) { +#if __has_builtin(__builtin_bswap128) + return __builtin_bswap128(__val); +#else + return static_cast<_Tp>(byteswap(static_cast(__val))) << 64 | + static_cast<_Tp>(byteswap(static_cast(__val >> 64))); +#endif // __has_builtin(__builtin_bswap128) +#endif // _LIBCPP_HAS_NO_INT128 + } else { + static_assert(sizeof(_Tp) == 0, "byteswap is unimplemented for integral types of this size"); + } +} + +#endif // _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BYTESWAP_H diff --git a/lib/libcxx/include/__bit_reference b/lib/libcxx/include/__bit_reference index a02492c077..a60a5c7219 100644 --- a/lib/libcxx/include/__bit_reference +++ b/lib/libcxx/include/__bit_reference @@ -10,8 +10,8 @@ #ifndef _LIBCPP___BIT_REFERENCE #define _LIBCPP___BIT_REFERENCE -#include <__config> #include <__bits> +#include <__config> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/lib/libcxx/include/__bsd_locale_defaults.h b/lib/libcxx/include/__bsd_locale_defaults.h index 2ace2a21cb..0d6506c625 100644 --- a/lib/libcxx/include/__bsd_locale_defaults.h +++ b/lib/libcxx/include/__bsd_locale_defaults.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===---------------------- __bsd_locale_defaults.h -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libcxx/include/__bsd_locale_fallbacks.h b/lib/libcxx/include/__bsd_locale_fallbacks.h index ed0eabf60e..a5788d9777 100644 --- a/lib/libcxx/include/__bsd_locale_fallbacks.h +++ b/lib/libcxx/include/__bsd_locale_fallbacks.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===---------------------- __bsd_locale_fallbacks.h ----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -30,6 +30,7 @@ decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) return MB_CUR_MAX; } +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_INLINE_VISIBILITY wint_t __libcpp_btowc_l(int __c, locale_t __l) { @@ -88,6 +89,7 @@ size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __libcpp_locale_guard __current(__l); return mbrlen(__s, __n, __ps); } +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_INLINE_VISIBILITY lconv *__libcpp_localeconv_l(locale_t __l) @@ -96,6 +98,7 @@ lconv *__libcpp_localeconv_l(locale_t __l) return localeconv(); } +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, mbstate_t *__ps, locale_t __l) @@ -103,8 +106,9 @@ size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, __libcpp_locale_guard __current(__l); return mbsrtowcs(__dest, __src, __len, __ps); } +#endif -inline +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -114,7 +118,7 @@ int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__forma return __res; } -inline +inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -124,7 +128,7 @@ int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) { return __res; } -inline +inline _LIBCPP_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); diff --git a/lib/libcxx/include/__charconv/chars_format.h b/lib/libcxx/include/__charconv/chars_format.h new file mode 100644 index 0000000000..22e70b56fb --- /dev/null +++ b/lib/libcxx/include/__charconv/chars_format.h @@ -0,0 +1,77 @@ +// -*- 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_CHARS_FORMAT_H +#define _LIBCPP___CHARCONV_CHARS_FORMAT_H + +#include <__config> +#include <__utility/to_underlying.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_CXX03_LANG + +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_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_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_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_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& +operator&=(chars_format& __x, chars_format __y) { + __x = __x & __y; + return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& +operator|=(chars_format& __x, chars_format __y) { + __x = __x | __y; + return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& +operator^=(chars_format& __x, chars_format __y) { + __x = __x ^ __y; + return __x; +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_CHARS_FORMAT_H diff --git a/lib/libcxx/include/__charconv/from_chars_result.h b/lib/libcxx/include/__charconv/from_chars_result.h new file mode 100644 index 0000000000..fbd7d50811 --- /dev/null +++ b/lib/libcxx/include/__charconv/from_chars_result.h @@ -0,0 +1,37 @@ +// -*- 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_RESULT_H +#define _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H + +#include <__config> +#include <__errc> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_CXX03_LANG + +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; +# endif +}; + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H diff --git a/lib/libcxx/include/__charconv/to_chars_result.h b/lib/libcxx/include/__charconv/to_chars_result.h new file mode 100644 index 0000000000..f515ee3122 --- /dev/null +++ b/lib/libcxx/include/__charconv/to_chars_result.h @@ -0,0 +1,37 @@ +// -*- 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_RESULT_H +#define _LIBCPP___CHARCONV_TO_CHARS_RESULT_H + +#include <__config> +#include <__errc> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_CXX03_LANG + +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; +# endif +}; + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS_RESULT_H diff --git a/lib/libcxx/include/__chrono/calendar.h b/lib/libcxx/include/__chrono/calendar.h new file mode 100644 index 0000000000..745f7f5cf5 --- /dev/null +++ b/lib/libcxx/include/__chrono/calendar.h @@ -0,0 +1,1276 @@ +// -*- 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_CALENDAR_H +#define _LIBCPP___CHRONO_CALENDAR_H + +#include <__chrono/duration.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +struct local_t {}; +template +using local_time = time_point; +using local_seconds = local_time; +using local_days = local_time; + +struct last_spec { explicit last_spec() = default; }; + +class day { +private: + unsigned char __d; +public: + day() = default; + explicit inline constexpr day(unsigned __val) noexcept : __d(static_cast(__val)) {} + inline constexpr day& operator++() noexcept { ++__d; return *this; } + inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } + inline constexpr day& operator--() noexcept { --__d; return *this; } + inline constexpr day operator--(int) noexcept { day __tmp = *this; --(*this); return __tmp; } + constexpr day& operator+=(const days& __dd) noexcept; + constexpr day& operator-=(const days& __dd) noexcept; + explicit inline constexpr operator unsigned() const noexcept { return __d; } + inline constexpr bool ok() const noexcept { return __d >= 1 && __d <= 31; } + }; + + +inline constexpr +bool operator==(const day& __lhs, const day& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +inline constexpr +bool operator!=(const day& __lhs, const day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const day& __lhs, const day& __rhs) noexcept +{ return static_cast(__lhs) < static_cast(__rhs); } + +inline constexpr +bool operator> (const day& __lhs, const day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const day& __lhs, const day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const day& __lhs, const day& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +day operator+ (const day& __lhs, const days& __rhs) noexcept +{ return day(static_cast(__lhs) + __rhs.count()); } + +inline constexpr +day operator+ (const days& __lhs, const day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +day operator- (const day& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +days operator-(const day& __lhs, const day& __rhs) noexcept +{ return days(static_cast(static_cast(__lhs)) - + static_cast(static_cast(__rhs))); } + +inline constexpr day& day::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +inline constexpr day& day::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + + +class month { +private: + unsigned char __m; +public: + month() = default; + explicit inline constexpr month(unsigned __val) noexcept : __m(static_cast(__val)) {} + inline constexpr month& operator++() noexcept { ++__m; return *this; } + inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } + inline constexpr month& operator--() noexcept { --__m; return *this; } + inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } + constexpr month& operator+=(const months& __m1) noexcept; + constexpr month& operator-=(const months& __m1) noexcept; + explicit inline constexpr operator unsigned() const noexcept { return __m; } + inline constexpr bool ok() const noexcept { return __m >= 1 && __m <= 12; } +}; + + +inline constexpr +bool operator==(const month& __lhs, const month& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +inline constexpr +bool operator!=(const month& __lhs, const month& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const month& __lhs, const month& __rhs) noexcept +{ return static_cast(__lhs) < static_cast(__rhs); } + +inline constexpr +bool operator> (const month& __lhs, const month& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month& __lhs, const month& __rhs) noexcept +{ return !(__rhs < __lhs); } + +inline constexpr +bool operator>=(const month& __lhs, const month& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +month operator+ (const month& __lhs, const months& __rhs) noexcept +{ + auto const __mu = static_cast(static_cast(__lhs)) + (__rhs.count() - 1); + auto const __yr = (__mu >= 0 ? __mu : __mu - 11) / 12; + return month{static_cast(__mu - __yr * 12 + 1)}; +} + +inline constexpr +month operator+ (const months& __lhs, const month& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +month operator- (const month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +months operator-(const month& __lhs, const month& __rhs) noexcept +{ + auto const __dm = static_cast(__lhs) - static_cast(__rhs); + return months(__dm <= 11 ? __dm : __dm + 12); +} + +inline constexpr month& month::operator+=(const months& __dm) noexcept +{ *this = *this + __dm; return *this; } + +inline constexpr month& month::operator-=(const months& __dm) noexcept +{ *this = *this - __dm; return *this; } + + +class year { +private: + short __y; +public: + year() = default; + explicit inline constexpr year(int __val) noexcept : __y(static_cast(__val)) {} + + inline constexpr year& operator++() noexcept { ++__y; return *this; } + inline constexpr year operator++(int) noexcept { year __tmp = *this; ++(*this); return __tmp; } + inline constexpr year& operator--() noexcept { --__y; return *this; } + inline constexpr year operator--(int) noexcept { year __tmp = *this; --(*this); return __tmp; } + constexpr year& operator+=(const years& __dy) noexcept; + constexpr year& operator-=(const years& __dy) noexcept; + inline constexpr year operator+() const noexcept { return *this; } + inline constexpr year operator-() const noexcept { return year{-__y}; } + + inline constexpr bool is_leap() const noexcept { return __y % 4 == 0 && (__y % 100 != 0 || __y % 400 == 0); } + explicit inline constexpr operator int() const noexcept { return __y; } + constexpr bool ok() const noexcept; + static inline constexpr year min() noexcept { return year{-32767}; } + static inline constexpr year max() noexcept { return year{ 32767}; } +}; + + +inline constexpr +bool operator==(const year& __lhs, const year& __rhs) noexcept +{ return static_cast(__lhs) == static_cast(__rhs); } + +inline constexpr +bool operator!=(const year& __lhs, const year& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year& __lhs, const year& __rhs) noexcept +{ return static_cast(__lhs) < static_cast(__rhs); } + +inline constexpr +bool operator> (const year& __lhs, const year& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year& __lhs, const year& __rhs) noexcept +{ return !(__rhs < __lhs); } + +inline constexpr +bool operator>=(const year& __lhs, const year& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +year operator+ (const year& __lhs, const years& __rhs) noexcept +{ return year(static_cast(__lhs) + __rhs.count()); } + +inline constexpr +year operator+ (const years& __lhs, const year& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year operator- (const year& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +years operator-(const year& __lhs, const year& __rhs) noexcept +{ return years{static_cast(__lhs) - static_cast(__rhs)}; } + + +inline constexpr year& year::operator+=(const years& __dy) noexcept +{ *this = *this + __dy; return *this; } + +inline constexpr year& year::operator-=(const years& __dy) noexcept +{ *this = *this - __dy; return *this; } + +inline constexpr bool year::ok() const noexcept +{ return static_cast(min()) <= __y && __y <= static_cast(max()); } + +class weekday_indexed; +class weekday_last; + +class weekday { +private: + unsigned char __wd; + static constexpr unsigned char __weekday_from_days(int __days) noexcept; +public: + weekday() = default; + inline explicit constexpr weekday(unsigned __val) noexcept : __wd(static_cast(__val == 7 ? 0 : __val)) {} + inline constexpr weekday(const sys_days& __sysd) noexcept + : __wd(__weekday_from_days(__sysd.time_since_epoch().count())) {} + inline explicit constexpr weekday(const local_days& __locd) noexcept + : __wd(__weekday_from_days(__locd.time_since_epoch().count())) {} + + inline constexpr weekday& operator++() noexcept { __wd = (__wd == 6 ? 0 : __wd + 1); return *this; } + inline constexpr weekday operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; } + inline constexpr weekday& operator--() noexcept { __wd = (__wd == 0 ? 6 : __wd - 1); return *this; } + inline constexpr weekday operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; } + constexpr weekday& operator+=(const days& __dd) noexcept; + constexpr weekday& operator-=(const days& __dd) noexcept; + inline constexpr unsigned c_encoding() const noexcept { return __wd; } + inline constexpr unsigned iso_encoding() const noexcept { return __wd == 0u ? 7 : __wd; } + inline constexpr bool ok() const noexcept { return __wd <= 6; } + constexpr weekday_indexed operator[](unsigned __index) const noexcept; + constexpr weekday_last operator[](last_spec) const noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#weekday_from_days +inline constexpr +unsigned char weekday::__weekday_from_days(int __days) noexcept +{ + return static_cast( + static_cast(__days >= -4 ? (__days+4) % 7 : (__days+5) % 7 + 6) + ); +} + +inline constexpr +bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept +{ return __lhs.c_encoding() == __rhs.c_encoding(); } + +inline constexpr +bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept +{ return __lhs.c_encoding() < __rhs.c_encoding(); } + +inline constexpr +bool operator> (const weekday& __lhs, const weekday& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs < __rhs); } + +constexpr weekday operator+(const weekday& __lhs, const days& __rhs) noexcept +{ + auto const __mu = static_cast(__lhs.c_encoding()) + __rhs.count(); + auto const __yr = (__mu >= 0 ? __mu : __mu - 6) / 7; + return weekday{static_cast(__mu - __yr * 7)}; +} + +constexpr weekday operator+(const days& __lhs, const weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr weekday operator-(const weekday& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +constexpr days operator-(const weekday& __lhs, const weekday& __rhs) noexcept +{ + const int __wdu = __lhs.c_encoding() - __rhs.c_encoding(); + const int __wk = (__wdu >= 0 ? __wdu : __wdu-6) / 7; + return days{__wdu - __wk * 7}; +} + +inline constexpr weekday& weekday::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +inline constexpr weekday& weekday::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + + +class weekday_indexed { +private: + chrono::weekday __wd; + unsigned char __idx; +public: + weekday_indexed() = default; + inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept + : __wd{__wdval}, __idx(__idxval) {} + inline constexpr chrono::weekday weekday() const noexcept { return __wd; } + inline constexpr unsigned index() const noexcept { return __idx; } + inline constexpr bool ok() const noexcept { return __wd.ok() && __idx >= 1 && __idx <= 5; } +}; + +inline constexpr +bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); } + +inline constexpr +bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +class weekday_last { +private: + chrono::weekday __wd; +public: + explicit constexpr weekday_last(const chrono::weekday& __val) noexcept + : __wd{__val} {} + constexpr chrono::weekday weekday() const noexcept { return __wd; } + constexpr bool ok() const noexcept { return __wd.ok(); } +}; + +inline constexpr +bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday(); } + +inline constexpr +bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; } + +inline constexpr +weekday_last weekday::operator[](last_spec) const noexcept { return weekday_last{*this}; } + + +inline constexpr last_spec last{}; +inline constexpr weekday Sunday{0}; +inline constexpr weekday Monday{1}; +inline constexpr weekday Tuesday{2}; +inline constexpr weekday Wednesday{3}; +inline constexpr weekday Thursday{4}; +inline constexpr weekday Friday{5}; +inline constexpr weekday Saturday{6}; + +inline constexpr month January{1}; +inline constexpr month February{2}; +inline constexpr month March{3}; +inline constexpr month April{4}; +inline constexpr month May{5}; +inline constexpr month June{6}; +inline constexpr month July{7}; +inline constexpr month August{8}; +inline constexpr month September{9}; +inline constexpr month October{10}; +inline constexpr month November{11}; +inline constexpr month December{12}; + + +class month_day { +private: + chrono::month __m; + chrono::day __d; +public: + month_day() = default; + constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept + : __m{__mval}, __d{__dval} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::day day() const noexcept { return __d; } + constexpr bool ok() const noexcept; +}; + +inline constexpr +bool month_day::ok() const noexcept +{ + if (!__m.ok()) return false; + const unsigned __dval = static_cast(__d); + if (__dval < 1 || __dval > 31) return false; + if (__dval <= 29) return true; +// Now we've got either 30 or 31 + const unsigned __mval = static_cast(__m); + if (__mval == 2) return false; + if (__mval == 4 || __mval == 6 || __mval == 9 || __mval == 11) + return __dval == 30; + return true; +} + +inline constexpr +bool operator==(const month_day& __lhs, const month_day& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +inline constexpr +bool operator!=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +month_day operator/(const month& __lhs, const day& __rhs) noexcept +{ return month_day{__lhs, __rhs}; } + +constexpr +month_day operator/(const day& __lhs, const month& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +month_day operator/(const month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +constexpr +month_day operator/(int __lhs, const day& __rhs) noexcept +{ return month(__lhs) / __rhs; } + +constexpr +month_day operator/(const day& __lhs, int __rhs) noexcept +{ return month(__rhs) / __lhs; } + + +inline constexpr +bool operator< (const month_day& __lhs, const month_day& __rhs) noexcept +{ return __lhs.month() != __rhs.month() ? __lhs.month() < __rhs.month() : __lhs.day() < __rhs.day(); } + +inline constexpr +bool operator> (const month_day& __lhs, const month_day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__lhs < __rhs); } + + + +class month_day_last { +private: + chrono::month __m; +public: + explicit constexpr month_day_last(const chrono::month& __val) noexcept + : __m{__val} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr bool ok() const noexcept { return __m.ok(); } +}; + +inline constexpr +bool operator==(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __lhs.month() == __rhs.month(); } + +inline constexpr +bool operator!=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __lhs.month() < __rhs.month(); } + +inline constexpr +bool operator> (const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +month_day_last operator/(const month& __lhs, last_spec) noexcept +{ return month_day_last{__lhs}; } + +inline constexpr +month_day_last operator/(last_spec, const month& __rhs) noexcept +{ return month_day_last{__rhs}; } + +inline constexpr +month_day_last operator/(int __lhs, last_spec) noexcept +{ return month_day_last{month(__lhs)}; } + +inline constexpr +month_day_last operator/(last_spec, int __rhs) noexcept +{ return month_day_last{month(__rhs)}; } + + +class month_weekday { +private: + chrono::month __m; + chrono::weekday_indexed __wdi; +public: + constexpr month_weekday(const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept + : __m{__mval}, __wdi{__wdival} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } + inline constexpr bool ok() const noexcept { return __m.ok() && __wdi.ok(); } +}; + +inline constexpr +bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } + +inline constexpr +bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{__lhs, __rhs}; } + +inline constexpr +month_weekday operator/(int __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{month(__lhs), __rhs}; } + +inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, const month& __rhs) noexcept +{ return month_weekday{__rhs, __lhs}; } + +inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, int __rhs) noexcept +{ return month_weekday{month(__rhs), __lhs}; } + + +class month_weekday_last { + chrono::month __m; + chrono::weekday_last __wdl; + public: + constexpr month_weekday_last(const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept + : __m{__mval}, __wdl{__wdlval} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } + inline constexpr bool ok() const noexcept { return __m.ok() && __wdl.ok(); } +}; + +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(); } + +inline constexpr +bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +inline constexpr +month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{__lhs, __rhs}; } + +inline constexpr +month_weekday_last operator/(int __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{month(__lhs), __rhs}; } + +inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, const month& __rhs) noexcept +{ return month_weekday_last{__rhs, __lhs}; } + +inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept +{ return month_weekday_last{month(__rhs), __lhs}; } + + +class year_month { + chrono::year __y; + chrono::month __m; +public: + year_month() = default; + constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept + : __y{__yval}, __m{__mval} {} + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m += __dm; return *this; } + inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m -= __dm; return *this; } + inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y += __dy; return *this; } + inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y -= __dy; return *this; } + inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok(); } +}; + +inline constexpr +year_month operator/(const year& __y, const month& __m) noexcept { return year_month{__y, __m}; } + +inline constexpr +year_month operator/(const year& __y, int __m) noexcept { return year_month{__y, month(__m)}; } + +inline constexpr +bool operator==(const year_month& __lhs, const year_month& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month(); } + +inline constexpr +bool operator!=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month& __lhs, const year_month& __rhs) noexcept +{ return __lhs.year() != __rhs.year() ? __lhs.year() < __rhs.year() : __lhs.month() < __rhs.month(); } + +inline constexpr +bool operator> (const year_month& __lhs, const year_month& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__lhs < __rhs); } + +constexpr year_month operator+(const year_month& __lhs, const months& __rhs) noexcept +{ + int __dmi = static_cast(static_cast(__lhs.month())) - 1 + __rhs.count(); + const int __dy = (__dmi >= 0 ? __dmi : __dmi-11) / 12; + __dmi = __dmi - __dy * 12 + 1; + return (__lhs.year() + years(__dy)) / month(static_cast(__dmi)); +} + +constexpr year_month operator+(const months& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr year_month operator+(const year_month& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month(); } + +constexpr year_month operator+(const years& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr months operator-(const year_month& __lhs, const year_month& __rhs) noexcept +{ return (__lhs.year() - __rhs.year()) + months(static_cast(__lhs.month()) - static_cast(__rhs.month())); } + +constexpr year_month operator-(const year_month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +constexpr year_month operator-(const year_month& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +class year_month_day_last; + +class year_month_day { +private: + chrono::year __y; + chrono::month __m; + chrono::day __d; +public: + year_month_day() = default; + inline constexpr year_month_day( + const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept + : __y{__yval}, __m{__mval}, __d{__dval} {} + constexpr year_month_day(const year_month_day_last& __ymdl) noexcept; + inline constexpr year_month_day(const sys_days& __sysd) noexcept + : year_month_day(__from_days(__sysd.time_since_epoch())) {} + inline explicit constexpr year_month_day(const local_days& __locd) noexcept + : year_month_day(__from_days(__locd.time_since_epoch())) {} + + constexpr year_month_day& operator+=(const months& __dm) noexcept; + constexpr year_month_day& operator-=(const months& __dm) noexcept; + constexpr year_month_day& operator+=(const years& __dy) noexcept; + constexpr year_month_day& operator-=(const years& __dy) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::day day() const noexcept { return __d; } + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + + constexpr bool ok() const noexcept; + + static constexpr year_month_day __from_days(days __d) noexcept; + constexpr days __to_days() const noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#civil_from_days +inline constexpr +year_month_day +year_month_day::__from_days(days __d) noexcept +{ + static_assert(numeric_limits::digits >= 18, ""); + static_assert(numeric_limits::digits >= 20 , ""); + const int __z = __d.count() + 719468; + const int __era = (__z >= 0 ? __z : __z - 146096) / 146097; + const unsigned __doe = static_cast(__z - __era * 146097); // [0, 146096] + const unsigned __yoe = (__doe - __doe/1460 + __doe/36524 - __doe/146096) / 365; // [0, 399] + const int __yr = static_cast(__yoe) + __era * 400; + const unsigned __doy = __doe - (365 * __yoe + __yoe/4 - __yoe/100); // [0, 365] + const unsigned __mp = (5 * __doy + 2)/153; // [0, 11] + const unsigned __dy = __doy - (153 * __mp + 2)/5 + 1; // [1, 31] + const unsigned __mth = __mp + (__mp < 10 ? 3 : -9); // [1, 12] + return year_month_day{chrono::year{__yr + (__mth <= 2)}, chrono::month{__mth}, chrono::day{__dy}}; +} + +// https://howardhinnant.github.io/date_algorithms.html#days_from_civil +inline constexpr days year_month_day::__to_days() const noexcept +{ + static_assert(numeric_limits::digits >= 18, ""); + static_assert(numeric_limits::digits >= 20 , ""); + + const int __yr = static_cast(__y) - (__m <= February); + const unsigned __mth = static_cast(__m); + const unsigned __dy = static_cast(__d); + + const int __era = (__yr >= 0 ? __yr : __yr - 399) / 400; + const unsigned __yoe = static_cast(__yr - __era * 400); // [0, 399] + const unsigned __doy = (153 * (__mth + (__mth > 2 ? -3 : 9)) + 2) / 5 + __dy-1; // [0, 365] + const unsigned __doe = __yoe * 365 + __yoe/4 - __yoe/100 + __doy; // [0, 146096] + return days{__era * 146097 + static_cast(__doe) - 719468}; +} + +inline constexpr +bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +inline constexpr +bool operator!=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ + if (__lhs.year() < __rhs.year()) return true; + if (__lhs.year() > __rhs.year()) return false; + if (__lhs.month() < __rhs.month()) return true; + if (__lhs.month() > __rhs.month()) return false; + return __lhs.day() < __rhs.day(); +} + +inline constexpr +bool operator> (const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +year_month_day operator/(const year_month& __lhs, const day& __rhs) noexcept +{ return year_month_day{__lhs.year(), __lhs.month(), __rhs}; } + +inline constexpr +year_month_day operator/(const year_month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +inline constexpr +year_month_day operator/(const year& __lhs, const month_day& __rhs) noexcept +{ return __lhs / __rhs.month() / __rhs.day(); } + +inline constexpr +year_month_day operator/(int __lhs, const month_day& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_day operator/(const month_day& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_day operator/(const month_day& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_day operator+(const year_month_day& __lhs, const months& __rhs) noexcept +{ return (__lhs.year()/__lhs.month() + __rhs)/__lhs.day(); } + +inline constexpr +year_month_day operator+(const months& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day operator-(const year_month_day& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +year_month_day operator+(const year_month_day& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month() / __lhs.day(); } + +inline constexpr +year_month_day operator+(const years& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day operator-(const year_month_day& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr year_month_day& year_month_day::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_day& year_month_day::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_day& year_month_day::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_day& year_month_day::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class year_month_day_last { +private: + chrono::year __y; + chrono::month_day_last __mdl; +public: + constexpr year_month_day_last(const year& __yval, const month_day_last& __mdlval) noexcept + : __y{__yval}, __mdl{__mdlval} {} + + constexpr year_month_day_last& operator+=(const months& __m) noexcept; + constexpr year_month_day_last& operator-=(const months& __m) noexcept; + constexpr year_month_day_last& operator+=(const years& __y) noexcept; + constexpr year_month_day_last& operator-=(const years& __y) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __mdl.month(); } + inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; } + constexpr chrono::day day() const noexcept; + inline constexpr operator sys_days() const noexcept { return sys_days{year()/month()/day()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{year()/month()/day()}; } + inline constexpr bool ok() const noexcept { return __y.ok() && __mdl.ok(); } +}; + +inline constexpr +chrono::day year_month_day_last::day() const noexcept +{ + constexpr chrono::day __d[] = + { + chrono::day(31), chrono::day(28), chrono::day(31), + chrono::day(30), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(30), chrono::day(31) + }; + return (month() != February || !__y.is_leap()) && month().ok() ? + __d[static_cast(month()) - 1] : chrono::day{29}; +} + +inline constexpr +bool operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); } + +inline constexpr +bool operator!=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ + if (__lhs.year() < __rhs.year()) return true; + if (__lhs.year() > __rhs.year()) return false; + return __lhs.month_day_last() < __rhs.month_day_last(); +} + +inline constexpr +bool operator> (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr year_month_day_last operator/(const year_month& __lhs, last_spec) noexcept +{ return year_month_day_last{__lhs.year(), month_day_last{__lhs.month()}}; } + +inline constexpr year_month_day_last operator/(const year& __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{__lhs, __rhs}; } + +inline constexpr year_month_day_last operator/(int __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{year{__lhs}, __rhs}; } + +inline constexpr year_month_day_last operator/(const month_day_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr year_month_day_last operator/(const month_day_last& __lhs, int __rhs) noexcept +{ return year{__rhs} / __lhs; } + + +inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / last; } + +inline constexpr +year_month_day_last operator+(const months& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return year_month_day_last{__lhs.year() + __rhs, __lhs.month_day_last()}; } + +inline constexpr +year_month_day_last operator+(const years& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr year_month_day_last& year_month_day_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +inline constexpr year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept + : __y{__ymdl.year()}, __m{__ymdl.month()}, __d{__ymdl.day()} {} + +inline constexpr bool year_month_day::ok() const noexcept +{ + if (!__y.ok() || !__m.ok()) return false; + return chrono::day{1} <= __d && __d <= (__y / __m / last).day(); +} + +class year_month_weekday { + chrono::year __y; + chrono::month __m; + chrono::weekday_indexed __wdi; +public: + year_month_weekday() = default; + constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_indexed& __wdival) noexcept + : __y{__yval}, __m{__mval}, __wdi{__wdival} {} + constexpr year_month_weekday(const sys_days& __sysd) noexcept + : year_month_weekday(__from_days(__sysd.time_since_epoch())) {} + inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept + : year_month_weekday(__from_days(__locd.time_since_epoch())) {} + constexpr year_month_weekday& operator+=(const months& m) noexcept; + constexpr year_month_weekday& operator-=(const months& m) noexcept; + constexpr year_month_weekday& operator+=(const years& y) noexcept; + constexpr year_month_weekday& operator-=(const years& y) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday weekday() const noexcept { return __wdi.weekday(); } + inline constexpr unsigned index() const noexcept { return __wdi.index(); } + inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } + + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + inline constexpr bool ok() const noexcept + { + if (!__y.ok() || !__m.ok() || !__wdi.ok()) return false; + if (__wdi.index() <= 4) return true; + auto __nth_weekday_day = + __wdi.weekday() - + chrono::weekday{static_cast(__y / __m / 1)} + + days{(__wdi.index() - 1) * 7 + 1}; + return static_cast(__nth_weekday_day.count()) <= + static_cast((__y / __m / last).day()); + } + + static constexpr year_month_weekday __from_days(days __d) noexcept; + constexpr days __to_days() const noexcept; +}; + +inline constexpr +year_month_weekday year_month_weekday::__from_days(days __d) noexcept +{ + const sys_days __sysd{__d}; + const chrono::weekday __wd = chrono::weekday(__sysd); + const year_month_day __ymd = year_month_day(__sysd); + return year_month_weekday{__ymd.year(), __ymd.month(), + __wd[(static_cast(__ymd.day())-1)/7+1]}; +} + +inline constexpr +days year_month_weekday::__to_days() const noexcept +{ + const sys_days __sysd = sys_days(__y/__m/1); + return (__sysd + (__wdi.weekday() - chrono::weekday(__sysd) + days{(__wdi.index()-1)*7})) + .time_since_epoch(); +} + +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(); } + +inline constexpr +bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept +{ return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; } + +inline constexpr +year_month_weekday operator/(const year& __lhs, const month_weekday& __rhs) noexcept +{ return year_month_weekday{__lhs, __rhs.month(), __rhs.weekday_indexed()}; } + +inline constexpr +year_month_weekday operator/(int __lhs, const month_weekday& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_indexed(); } + +inline constexpr +year_month_weekday operator+(const months& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return year_month_weekday{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_indexed()}; } + +inline constexpr +year_month_weekday operator+(const years& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + + +inline constexpr year_month_weekday& year_month_weekday::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class year_month_weekday_last { +private: + chrono::year __y; + chrono::month __m; + chrono::weekday_last __wdl; +public: + constexpr year_month_weekday_last(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_last& __wdlval) noexcept + : __y{__yval}, __m{__mval}, __wdl{__wdlval} {} + constexpr year_month_weekday_last& operator+=(const months& __dm) noexcept; + constexpr year_month_weekday_last& operator-=(const months& __dm) noexcept; + constexpr year_month_weekday_last& operator+=(const years& __dy) noexcept; + constexpr year_month_weekday_last& operator-=(const years& __dy) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday weekday() const noexcept { return __wdl.weekday(); } + inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __wdl.ok(); } + + constexpr days __to_days() const noexcept; + +}; + +inline constexpr +days year_month_weekday_last::__to_days() const noexcept +{ + const sys_days __last = sys_days{__y/__m/last}; + return (__last - (chrono::weekday{__last} - __wdl.weekday())).time_since_epoch(); + +} + +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(); } + +inline constexpr +bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +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}; } + +inline constexpr +year_month_weekday_last operator/(const year& __lhs, const month_weekday_last& __rhs) noexcept +{ return year_month_weekday_last{__lhs, __rhs.month(), __rhs.weekday_last()}; } + +inline constexpr +year_month_weekday_last operator/(int __lhs, const month_weekday_last& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_last(); } + +inline constexpr +year_month_weekday_last operator+(const months& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return year_month_weekday_last{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_last()}; } + +inline constexpr +year_month_weekday_last operator+(const years& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + + +template +class hh_mm_ss +{ +private: + static_assert(__is_duration<_Duration>::value, "template parameter of hh_mm_ss must be a std::chrono::duration"); + using __CommonType = common_type_t<_Duration, chrono::seconds>; + + static constexpr uint64_t __pow10(unsigned __exp) + { + uint64_t __ret = 1; + for (unsigned __i = 0; __i < __exp; ++__i) + __ret *= 10U; + return __ret; + } + + static constexpr unsigned __width(uint64_t __n, uint64_t __d = 10, unsigned __w = 0) + { + if (__n >= 2 && __d != 0 && __w < 19) + return 1 + __width(__n, __d % __n * 10, __w+1); + return 0; + } + +public: + static unsigned constexpr fractional_width = __width(__CommonType::period::den) < 19 ? + __width(__CommonType::period::den) : 6u; + using precision = duration>; + + constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {} + + constexpr explicit hh_mm_ss(_Duration __d) noexcept : + __is_neg(__d < _Duration(0)), + __h(duration_cast (abs(__d))), + __m(duration_cast(abs(__d) - hours())), + __s(duration_cast(abs(__d) - hours() - minutes())), + __f(duration_cast (abs(__d) - hours() - minutes() - seconds())) + {} + + constexpr bool is_negative() const noexcept { return __is_neg; } + constexpr chrono::hours hours() const noexcept { return __h; } + constexpr chrono::minutes minutes() const noexcept { return __m; } + constexpr chrono::seconds seconds() const noexcept { return __s; } + constexpr precision subseconds() const noexcept { return __f; } + + constexpr precision to_duration() const noexcept + { + auto __dur = __h + __m + __s + __f; + return __is_neg ? -__dur : __dur; + } + + constexpr explicit operator precision() const noexcept { return to_duration(); } + +private: + bool __is_neg; + chrono::hours __h; + chrono::minutes __m; + chrono::seconds __s; + precision __f; +}; + +constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } +constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); } + +constexpr hours make12(const hours& __h) noexcept +{ + if (__h == hours( 0)) return hours(12); + else if (__h <= hours(12)) return __h; + else return __h - hours(12); +} + +constexpr hours make24(const hours& __h, bool __is_pm) noexcept +{ + if (__is_pm) + return __h == hours(12) ? __h : __h + hours(12); + else + return __h == hours(12) ? hours(0) : __h; +} + +} // namespace chrono + +inline namespace literals +{ + inline namespace chrono_literals + { + constexpr chrono::day operator ""d(unsigned long long __d) noexcept + { + return chrono::day(static_cast(__d)); + } + + constexpr chrono::year operator ""y(unsigned long long __y) noexcept + { + return chrono::year(static_cast(__y)); + } +} // namespace chrono_literals +} // namespace literals + +namespace chrono { // hoist the literals into namespace std::chrono + using namespace literals::chrono_literals; +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_CALENDAR_H diff --git a/lib/libcxx/include/__chrono/convert_to_timespec.h b/lib/libcxx/include/__chrono/convert_to_timespec.h new file mode 100644 index 0000000000..0106e6dec3 --- /dev/null +++ b/lib/libcxx/include/__chrono/convert_to_timespec.h @@ -0,0 +1,55 @@ +// -*- 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_CONVERT_TO_TIMESPEC_H +#define _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H + +#include <__chrono/duration.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Convert a nanoseconds duration to the given TimeSpec type, which must have +// the same properties as std::timespec. +template +_LIBCPP_HIDE_FROM_ABI inline +_TimeSpec __convert_to_timespec(const chrono::nanoseconds& __ns) +{ + using namespace chrono; + seconds __s = duration_cast(__ns); + _TimeSpec __ts; + typedef decltype(__ts.tv_sec) __ts_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 = static_cast((__ns - __s).count()); + } + else + { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = 999999999; // (10^9 - 1) + } + + return __ts; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_CONVERT_TO_TIMESPEC_H diff --git a/lib/libcxx/include/__chrono/duration.h b/lib/libcxx/include/__chrono/duration.h new file mode 100644 index 0000000000..b7d88cb52e --- /dev/null +++ b/lib/libcxx/include/__chrono/duration.h @@ -0,0 +1,615 @@ +// -*- 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_DURATION_H +#define _LIBCPP___CHRONO_DURATION_H + +#include <__config> +#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 + +namespace chrono +{ + +template > class _LIBCPP_TEMPLATE_VIS duration; + +template +struct __is_duration : false_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +template +struct __is_duration > : true_type {}; + +} // namespace chrono + +template +struct _LIBCPP_TEMPLATE_VIS common_type, + chrono::duration<_Rep2, _Period2> > +{ + typedef chrono::duration::type, + typename __ratio_gcd<_Period1, _Period2>::type> type; +}; + +namespace chrono { + +// duration_cast + +template ::type, + bool = _Period::num == 1, + bool = _Period::den == 1> +struct __duration_cast; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, true, true> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + return _ToDuration(static_cast(__fd.count())); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, true, false> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) / static_cast<_Ct>(_Period::den))); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, false, true> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) * static_cast<_Ct>(_Period::num))); + } +}; + +template +struct __duration_cast<_FromDuration, _ToDuration, _Period, false, false> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _ToDuration operator()(const _FromDuration& __fd) const + { + typedef typename common_type::type _Ct; + return _ToDuration(static_cast( + static_cast<_Ct>(__fd.count()) * static_cast<_Ct>(_Period::num) + / static_cast<_Ct>(_Period::den))); + } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +duration_cast(const duration<_Rep, _Period>& __fd) +{ + return __duration_cast, _ToDuration>()(__fd); +} + +template +struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {}; + +#if _LIBCPP_STD_VER > 14 +template +inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value; +#endif + +template +struct _LIBCPP_TEMPLATE_VIS duration_values +{ +public: + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT {return _Rep(0);} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT {return numeric_limits<_Rep>::max();} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {return numeric_limits<_Rep>::lowest();} +}; + +#if _LIBCPP_STD_VER > 14 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +floor(const duration<_Rep, _Period>& __d) +{ + _ToDuration __t = duration_cast<_ToDuration>(__d); + if (__t > __d) + __t = __t - _ToDuration{1}; + return __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +ceil(const duration<_Rep, _Period>& __d) +{ + _ToDuration __t = duration_cast<_ToDuration>(__d); + if (__t < __d) + __t = __t + _ToDuration{1}; + return __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + _ToDuration +>::type +round(const duration<_Rep, _Period>& __d) +{ + _ToDuration __lower = floor<_ToDuration>(__d); + _ToDuration __upper = __lower + _ToDuration{1}; + auto __lowerDiff = __d - __lower; + auto __upperDiff = __upper - __d; + if (__lowerDiff < __upperDiff) + return __lower; + if (__lowerDiff > __upperDiff) + return __upper; + return __lower.count() & 1 ? __upper : __lower; +} +#endif + +// duration + +template +class _LIBCPP_TEMPLATE_VIS duration +{ + static_assert(!__is_duration<_Rep>::value, "A duration representation can not be a duration"); + static_assert(__is_ratio<_Period>::value, "Second template parameter of duration must be a std::ratio"); + static_assert(_Period::num > 0, "duration period must be positive"); + + template + struct __no_overflow + { + private: + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __n1 = _R1::num / __gcd_n1_n2; + static const intmax_t __d1 = _R1::den / __gcd_d1_d2; + static const intmax_t __n2 = _R2::num / __gcd_n1_n2; + static const intmax_t __d2 = _R2::den / __gcd_d1_d2; + static const intmax_t max = -((intmax_t(1) << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1); + + template + struct __mul // __overflow == false + { + static const intmax_t value = _Xp * _Yp; + }; + + template + struct __mul<_Xp, _Yp, true> + { + static const intmax_t value = 1; + }; + + public: + static const bool value = (__n1 <= max / __d2) && (__n2 <= max / __d1); + typedef ratio<__mul<__n1, __d2, !value>::value, + __mul<__n2, __d1, !value>::value> type; + }; + +public: + typedef _Rep rep; + typedef typename _Period::type period; +private: + rep __rep_; +public: + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +#ifndef _LIBCPP_CXX03_LANG + duration() = default; +#else + duration() {} +#endif + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + explicit duration(const _Rep2& __r, + typename enable_if + < + is_convertible::value && + (treat_as_floating_point::value || + !treat_as_floating_point<_Rep2>::value) + >::type* = nullptr) + : __rep_(__r) {} + + // conversions + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + duration(const duration<_Rep2, _Period2>& __d, + typename enable_if + < + __no_overflow<_Period2, period>::value && ( + treat_as_floating_point::value || + (__no_overflow<_Period2, period>::type::den == 1 && + !treat_as_floating_point<_Rep2>::value)) + >::type* = nullptr) + : __rep_(chrono::duration_cast(__d).count()) {} + + // observer + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR rep count() const {return __rep_;} + + // arithmetic + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type::type operator+() const {return typename common_type::type(*this);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename common_type::type operator-() const {return typename common_type::type(-__rep_);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator++() {++__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration operator++(int) {return duration(__rep_++);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator--() {--__rep_; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration operator--(int) {return duration(__rep_--);} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator+=(const duration& __d) {__rep_ += __d.count(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator-=(const duration& __d) {__rep_ -= __d.count(); return *this;} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator*=(const rep& rhs) {__rep_ *= rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator/=(const rep& rhs) {__rep_ /= rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator%=(const rep& rhs) {__rep_ %= rhs; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 duration& operator%=(const duration& rhs) {__rep_ %= rhs.count(); return *this;} + + // special values + + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {return duration(duration_values::zero());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {return duration(duration_values::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {return duration(duration_values::max());} +}; + +typedef duration nanoseconds; +typedef duration microseconds; +typedef duration milliseconds; +typedef duration seconds; +typedef duration< long, ratio< 60> > minutes; +typedef duration< long, ratio<3600> > hours; +#if _LIBCPP_STD_VER > 17 +typedef duration< int, ratio_multiply, hours::period>> days; +typedef duration< int, ratio_multiply, days::period>> weeks; +typedef duration< int, ratio_multiply, days::period>> years; +typedef duration< int, ratio_divide>> months; +#endif +// Duration == + +template +struct __duration_eq +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _RhsDuration& __rhs) const + { + typedef typename common_type<_LhsDuration, _RhsDuration>::type _Ct; + return _Ct(__lhs).count() == _Ct(__rhs).count(); + } +}; + +template +struct __duration_eq<_LhsDuration, _LhsDuration> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _LhsDuration& __rhs) const + {return __lhs.count() == __rhs.count();} +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __duration_eq, duration<_Rep2, _Period2> >()(__lhs, __rhs); +} + +// Duration != + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__lhs == __rhs); +} + +// Duration < + +template +struct __duration_lt +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _RhsDuration& __rhs) const + { + typedef typename common_type<_LhsDuration, _RhsDuration>::type _Ct; + return _Ct(__lhs).count() < _Ct(__rhs).count(); + } +}; + +template +struct __duration_lt<_LhsDuration, _LhsDuration> +{ + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + bool operator()(const _LhsDuration& __lhs, const _LhsDuration& __rhs) const + {return __lhs.count() < __rhs.count();} +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator< (const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __duration_lt, duration<_Rep2, _Period2> >()(__lhs, __rhs); +} + +// Duration > + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator> (const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return __rhs < __lhs; +} + +// Duration <= + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator<=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__rhs < __lhs); +} + +// Duration >= + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +bool +operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + return !(__lhs < __rhs); +} + +// Duration + + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(_Cd(__lhs).count() + _Cd(__rhs).count()); +} + +// Duration - + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(_Cd(__lhs).count() - _Cd(__rhs).count()); +} + +// Duration * + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() * static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + is_convertible<_Rep1, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) +{ + return __d * __s; +} + +// Duration / + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + !__is_duration<_Rep2>::value && + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() / static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type<_Rep1, _Rep2>::type +operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type, duration<_Rep2, _Period2> >::type _Ct; + return _Ct(__lhs).count() / _Ct(__rhs).count(); +} + +// Duration % + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename enable_if +< + !__is_duration<_Rep2>::value && + is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, + duration::type, _Period> +>::type +operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef duration<_Cr, _Period> _Cd; + return _Cd(_Cd(__d).count() % static_cast<_Cr>(__s)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +typename common_type, duration<_Rep2, _Period2> >::type +operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef typename common_type<_Rep1, _Rep2>::type _Cr; + typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; + return _Cd(static_cast<_Cr>(_Cd(__lhs).count()) % static_cast<_Cr>(_Cd(__rhs).count())); +} + +} // namespace chrono + +#if _LIBCPP_STD_VER > 11 +// Suffixes for duration literals [time.duration.literals] +inline namespace literals +{ + inline namespace chrono_literals + { + + constexpr chrono::hours operator""h(unsigned long long __h) + { + return chrono::hours(static_cast(__h)); + } + + constexpr chrono::duration> operator""h(long double __h) + { + return chrono::duration>(__h); + } + + + constexpr chrono::minutes operator""min(unsigned long long __m) + { + return chrono::minutes(static_cast(__m)); + } + + constexpr chrono::duration> operator""min(long double __m) + { + return chrono::duration> (__m); + } + + + constexpr chrono::seconds operator""s(unsigned long long __s) + { + return chrono::seconds(static_cast(__s)); + } + + constexpr chrono::duration operator""s(long double __s) + { + return chrono::duration (__s); + } + + + constexpr chrono::milliseconds operator""ms(unsigned long long __ms) + { + return chrono::milliseconds(static_cast(__ms)); + } + + constexpr chrono::duration operator""ms(long double __ms) + { + return chrono::duration(__ms); + } + + + constexpr chrono::microseconds operator""us(unsigned long long __us) + { + return chrono::microseconds(static_cast(__us)); + } + + constexpr chrono::duration operator""us(long double __us) + { + return chrono::duration (__us); + } + + + constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) + { + return chrono::nanoseconds(static_cast(__ns)); + } + + constexpr chrono::duration operator""ns(long double __ns) + { + return chrono::duration (__ns); + } + +} // namespace chrono_literals +} // namespace literals + +namespace chrono { // hoist the literals into namespace std::chrono + using namespace literals::chrono_literals; +} // namespace chrono + +#endif // _LIBCPP_STD_VER > 11 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_DURATION_H diff --git a/lib/libcxx/include/__chrono/file_clock.h b/lib/libcxx/include/__chrono/file_clock.h new file mode 100644 index 0000000000..cd8758f819 --- /dev/null +++ b/lib/libcxx/include/__chrono/file_clock.h @@ -0,0 +1,85 @@ +// -*- 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_FILE_CLOCK_H +#define _LIBCPP___CHRONO_FILE_CLOCK_H + +#include <__availability> +#include <__chrono/duration.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +struct _FilesystemClock; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// [time.clock.file], type file_clock +using file_clock = _VSTD_FS::_FilesystemClock; + +template +using file_time = time_point; + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 + +#ifndef _LIBCPP_CXX03_LANG +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +struct _FilesystemClock { +#if !defined(_LIBCPP_HAS_NO_INT128) + typedef __int128_t rep; + typedef nano period; +#else + typedef long long rep; + typedef nano period; +#endif + + typedef chrono::duration duration; + typedef chrono::time_point<_FilesystemClock> time_point; + + _LIBCPP_EXPORTED_FROM_ABI + static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false; + + _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_FUNC_VIS static time_point now() noexcept; + +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_HIDE_FROM_ABI + static chrono::sys_time<_Duration> to_sys(const chrono::file_time<_Duration>& __t) { + return chrono::sys_time<_Duration>(__t.time_since_epoch()); + } + + template + _LIBCPP_HIDE_FROM_ABI + 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 +}; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + +#endif // _LIBCPP___CHRONO_FILE_CLOCK_H diff --git a/lib/libcxx/include/__chrono/high_resolution_clock.h b/lib/libcxx/include/__chrono/high_resolution_clock.h new file mode 100644 index 0000000000..f5cde4acb9 --- /dev/null +++ b/lib/libcxx/include/__chrono/high_resolution_clock.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_HIGH_RESOLUTION_CLOCK_H +#define _LIBCPP___CHRONO_HIGH_RESOLUTION_CLOCK_H + +#include <__chrono/steady_clock.h> +#include <__chrono/system_clock.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +typedef steady_clock high_resolution_clock; +#else +typedef system_clock high_resolution_clock; +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_HIGH_RESOLUTION_CLOCK_H diff --git a/lib/libcxx/include/__chrono/steady_clock.h b/lib/libcxx/include/__chrono/steady_clock.h new file mode 100644 index 0000000000..5ba911df84 --- /dev/null +++ b/lib/libcxx/include/__chrono/steady_clock.h @@ -0,0 +1,44 @@ +// -*- 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_STEADY_CLOCK_H +#define _LIBCPP___CHRONO_STEADY_CLOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +class _LIBCPP_TYPE_VIS steady_clock +{ +public: + typedef nanoseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef chrono::time_point time_point; + static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = true; + + static time_point now() _NOEXCEPT; +}; +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_STEADY_CLOCK_H diff --git a/lib/libcxx/include/__chrono/system_clock.h b/lib/libcxx/include/__chrono/system_clock.h new file mode 100644 index 0000000000..9c977d369e --- /dev/null +++ b/lib/libcxx/include/__chrono/system_clock.h @@ -0,0 +1,54 @@ +// -*- 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_SYSTEM_CLOCK_H +#define _LIBCPP___CHRONO_SYSTEM_CLOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +class _LIBCPP_TYPE_VIS system_clock +{ +public: + typedef microseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef chrono::time_point time_point; + static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false; + + static time_point now() _NOEXCEPT; + static time_t to_time_t (const time_point& __t) _NOEXCEPT; + static time_point from_time_t(time_t __t) _NOEXCEPT; +}; + +#if _LIBCPP_STD_VER > 17 + +template +using sys_time = time_point; +using sys_seconds = sys_time; +using sys_days = sys_time; + +#endif + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_SYSTEM_CLOCK_H diff --git a/lib/libcxx/include/__chrono/time_point.h b/lib/libcxx/include/__chrono/time_point.h new file mode 100644 index 0000000000..c042e12514 --- /dev/null +++ b/lib/libcxx/include/__chrono/time_point.h @@ -0,0 +1,249 @@ +// -*- 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_TIME_POINT_H +#define _LIBCPP___CHRONO_TIME_POINT_H + +#include <__chrono/duration.h> +#include <__config> +#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 + +namespace chrono +{ + +template +class _LIBCPP_TEMPLATE_VIS time_point +{ + static_assert(__is_duration<_Duration>::value, + "Second template parameter of time_point must be a std::chrono::duration"); +public: + typedef _Clock clock; + typedef _Duration duration; + typedef typename duration::rep rep; + typedef typename duration::period period; +private: + duration __d_; + +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 time_point() : __d_(duration::zero()) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit time_point(const duration& __d) : __d_(__d) {} + + // conversions + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + time_point(const time_point& t, + typename enable_if + < + is_convertible<_Duration2, duration>::value + >::type* = nullptr) + : __d_(t.time_since_epoch()) {} + + // observer + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 duration time_since_epoch() const {return __d_;} + + // arithmetic + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} + + // special values + + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT {return time_point(duration::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT {return time_point(duration::max());} +}; + +} // namespace chrono + +template +struct _LIBCPP_TEMPLATE_VIS common_type, + chrono::time_point<_Clock, _Duration2> > +{ + typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type; +}; + +namespace chrono { + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +time_point<_Clock, _ToDuration> +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 +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +floor(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{floor<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +ceil(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{ceil<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + __is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration> +>::type +round(const time_point<_Clock, _Duration>& __t) +{ + return time_point<_Clock, _ToDuration>{round<_ToDuration>(__t.time_since_epoch())}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +typename enable_if +< + numeric_limits<_Rep>::is_signed, + duration<_Rep, _Period> +>::type +abs(duration<_Rep, _Period> __d) +{ + return __d >= __d.zero() ? +__d : -__d; +} +#endif // _LIBCPP_STD_VER > 14 + +// time_point == + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() == __rhs.time_since_epoch(); +} + +// time_point != + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__lhs == __rhs); +} + +// time_point < + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() < __rhs.time_since_epoch(); +} + +// time_point > + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __rhs < __lhs; +} + +// time_point <= + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__rhs < __lhs); +} + +// time_point >= + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +bool +operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return !(__lhs < __rhs); +} + +// time_point operator+(time_point x, duration y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr; + return _Tr (__lhs.time_since_epoch() + __rhs); +} + +// time_point operator+(duration x, time_point y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +time_point<_Clock, typename common_type, _Duration2>::type> +operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __rhs + __lhs; +} + +// time_point operator-(time_point x, duration y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) +{ + typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret; + return _Ret(__lhs.time_since_epoch() -__rhs); +} + +// duration operator-(time_point x, time_point y); + +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +typename common_type<_Duration1, _Duration2>::type +operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) +{ + return __lhs.time_since_epoch() - __rhs.time_since_epoch(); +} + +} // namespace chrono + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHRONO_TIME_POINT_H diff --git a/lib/libcxx/include/__compare/common_comparison_category.h b/lib/libcxx/include/__compare/common_comparison_category.h new file mode 100644 index 0000000000..37a28db1d6 --- /dev/null +++ b/lib/libcxx/include/__compare/common_comparison_category.h @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_COMMON_COMPARISON_CATEGORY_H +#define _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H + +#include <__compare/ordering.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __comp_detail { + +enum _ClassifyCompCategory : unsigned { + _None, + _PartialOrd, + _WeakOrd, + _StrongOrd, + _CCC_Size +}; + +template +_LIBCPP_HIDE_FROM_ABI +constexpr _ClassifyCompCategory __type_to_enum() noexcept { + if (is_same_v<_Tp, partial_ordering>) + return _PartialOrd; + if (is_same_v<_Tp, weak_ordering>) + return _WeakOrd; + if (is_same_v<_Tp, strong_ordering>) + return _StrongOrd; + return _None; +} + +template +_LIBCPP_HIDE_FROM_ABI +constexpr _ClassifyCompCategory +__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { + int __seen[_CCC_Size] = {}; + for (auto __type : __types) + ++__seen[__type]; + if (__seen[_None]) + return _None; + if (__seen[_PartialOrd]) + return _PartialOrd; + if (__seen[_WeakOrd]) + return _WeakOrd; + return _StrongOrd; +} + +template +_LIBCPP_HIDE_FROM_ABI +constexpr auto __get_comp_type() { + using _CCC = _ClassifyCompCategory; + constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; + constexpr _CCC _Cat = __compute_comp_type(__type_kinds); + if constexpr (_Cat == _None) + return void(); + else if constexpr (_Cat == _PartialOrd) + return partial_ordering::equivalent; + else if constexpr (_Cat == _WeakOrd) + return weak_ordering::equivalent; + else if constexpr (_Cat == _StrongOrd) + return strong_ordering::equivalent; + else + static_assert(_False, "unhandled case"); +} +} // namespace __comp_detail + +// [cmp.common], common comparison category type +template +struct _LIBCPP_TEMPLATE_VIS common_comparison_category { + using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); +}; + +template +using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H diff --git a/lib/libcxx/include/__compare/compare_partial_order_fallback.h b/lib/libcxx/include/__compare/compare_partial_order_fallback.h new file mode 100644 index 0000000000..64937eaf37 --- /dev/null +++ b/lib/libcxx/include/__compare/compare_partial_order_fallback.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___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/partial_order.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __compare_partial_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? partial_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? partial_ordering::less : + _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t) ? partial_ordering::greater : + partial_ordering::unordered; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_partial_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_partial_order_fallback = __compare_partial_order_fallback::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_PARTIAL_ORDER_FALLBACK diff --git a/lib/libcxx/include/__compare/compare_strong_order_fallback.h b/lib/libcxx/include/__compare/compare_strong_order_fallback.h new file mode 100644 index 0000000000..b7abef26e9 --- /dev/null +++ b/lib/libcxx/include/__compare/compare_strong_order_fallback.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_COMPARE_STRONG_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_STRONG_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/strong_order.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __compare_strong_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? strong_ordering::equal : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? strong_ordering::less : + strong_ordering::greater; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_strong_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_strong_order_fallback = __compare_strong_order_fallback::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_STRONG_ORDER_FALLBACK diff --git a/lib/libcxx/include/__compare/compare_three_way.h b/lib/libcxx/include/__compare/compare_three_way.h new file mode 100644 index 0000000000..ddd37890a4 --- /dev/null +++ b/lib/libcxx/include/__compare/compare_three_way.h @@ -0,0 +1,41 @@ +// -*- 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___COMPARE_COMPARE_THREE_WAY_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_H + +#include <__compare/three_way_comparable.h> +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +struct _LIBCPP_TEMPLATE_VIS compare_three_way +{ + template + requires three_way_comparable_with<_T1, _T2> + constexpr _LIBCPP_HIDE_FROM_ABI + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u))) + { return _VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u); } + + using is_transparent = void; +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_H diff --git a/lib/libcxx/include/__compare/compare_three_way_result.h b/lib/libcxx/include/__compare/compare_three_way_result.h new file mode 100644 index 0000000000..14908c6bbc --- /dev/null +++ b/lib/libcxx/include/__compare/compare_three_way_result.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___COMPARE_COMPARE_THREE_WAY_RESULT_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<_Tp, _Up, decltype( + declval<__make_const_lvalue_ref<_Tp>>() <=> declval<__make_const_lvalue_ref<_Up>>(), void() +)> { + using type = decltype(declval<__make_const_lvalue_ref<_Tp>>() <=> declval<__make_const_lvalue_ref<_Up>>()); +}; + +template +struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> { }; + +template +using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H diff --git a/lib/libcxx/include/__compare/compare_weak_order_fallback.h b/lib/libcxx/include/__compare/compare_weak_order_fallback.h new file mode 100644 index 0000000000..5a1807e697 --- /dev/null +++ b/lib/libcxx/include/__compare/compare_weak_order_fallback.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_COMPARE_WEAK_ORDER_FALLBACK +#define _LIBCPP___COMPARE_COMPARE_WEAK_ORDER_FALLBACK + +#include <__compare/ordering.h> +#include <__compare/weak_order.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __compare_weak_order_fallback { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + -> decltype( _VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))) + { return _VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater)) + -> decltype( _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater) + { + return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u) ? weak_ordering::equivalent : + _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u) ? weak_ordering::less : + weak_ordering::greater; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<1>()); } + }; +} // namespace __compare_weak_order_fallback + +inline namespace __cpo { + inline constexpr auto compare_weak_order_fallback = __compare_weak_order_fallback::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_WEAK_ORDER_FALLBACK diff --git a/lib/libcxx/include/__compare/is_eq.h b/lib/libcxx/include/__compare/is_eq.h new file mode 100644 index 0000000000..906cb0709e --- /dev/null +++ b/lib/libcxx/include/__compare/is_eq.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___COMPARE_IS_EQ_H +#define _LIBCPP___COMPARE_IS_EQ_H + +#include <__compare/ordering.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_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; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lt(partial_ordering __c) noexcept { return __c < 0; } +_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexcept { return __c <= 0; } +_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 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_IS_EQ_H diff --git a/lib/libcxx/include/__compare/ordering.h b/lib/libcxx/include/__compare/ordering.h new file mode 100644 index 0000000000..d4087bc85b --- /dev/null +++ b/lib/libcxx/include/__compare/ordering.h @@ -0,0 +1,319 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_ORDERING_H +#define _LIBCPP___COMPARE_ORDERING_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// exposition only +enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { + __less = -1, + __equiv = 0, + __greater = 1 +}; + +enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { + __unordered = -127 +}; + +class partial_ordering; +class weak_ordering; +class strong_ordering; + +template +inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); + +struct _CmpUnspecifiedParam { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL + _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} + + template>> + _CmpUnspecifiedParam(_Tp) = delete; +}; + +class partial_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr partial_ordering(_OrdResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr partial_ordering(_NCmpResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr bool __is_ordered() const noexcept { + return __value_ != _ValueT(_NCmpResult::__unordered); + } +public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); + } +private: + _ValueT __value_; +}; + +inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); +inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv); +inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); +inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); + +class weak_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + _LIBCPP_HIDE_FROM_ABI + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); +inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); +inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); + +class strong_ordering { + using _ValueT = signed char; + + _LIBCPP_HIDE_FROM_ABI + explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + // conversions + _LIBCPP_HIDE_FROM_ABI + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr operator weak_ordering() const noexcept { + return __value_ == 0 ? weak_ordering::equivalent + : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); + } + + // comparisons + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); +inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv); +inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv); +inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_ORDERING_H diff --git a/lib/libcxx/include/__compare/partial_order.h b/lib/libcxx/include/__compare/partial_order.h new file mode 100644 index 0000000000..cbadfcde73 --- /dev/null +++ b/lib/libcxx/include/__compare/partial_order.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_PARTIAL_ORDER +#define _LIBCPP___COMPARE_PARTIAL_ORDER + +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__compare/weak_order.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __partial_order { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) + noexcept(noexcept(partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return partial_ordering(_VSTD::weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()); } + }; +} // namespace __partial_order + +inline namespace __cpo { + inline constexpr auto partial_order = __partial_order::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_PARTIAL_ORDER diff --git a/lib/libcxx/include/__compare/strong_order.h b/lib/libcxx/include/__compare/strong_order.h new file mode 100644 index 0000000000..a0dc077047 --- /dev/null +++ b/lib/libcxx/include/__compare/strong_order.h @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_STRONG_ORDER +#define _LIBCPP___COMPARE_STRONG_ORDER + +#include <__bit/bit_cast.h> +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include +#include +#include +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __strong_order { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) + noexcept(noexcept(strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template> + requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> + _LIBCPP_HIDE_FROM_ABI static constexpr strong_ordering + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) noexcept + { + if constexpr (numeric_limits<_Dp>::is_iec559 && sizeof(_Dp) == sizeof(int32_t)) { + int32_t __rx = _VSTD::bit_cast(__t); + int32_t __ry = _VSTD::bit_cast(__u); + __rx = (__rx < 0) ? (numeric_limits::min() - __rx - 1) : __rx; + __ry = (__ry < 0) ? (numeric_limits::min() - __ry - 1) : __ry; + return (__rx <=> __ry); + } else if constexpr (numeric_limits<_Dp>::is_iec559 && sizeof(_Dp) == sizeof(int64_t)) { + int64_t __rx = _VSTD::bit_cast(__t); + int64_t __ry = _VSTD::bit_cast(__u); + __rx = (__rx < 0) ? (numeric_limits::min() - __rx - 1) : __rx; + __ry = (__ry < 0) ? (numeric_limits::min() - __ry - 1) : __ry; + return (__rx <=> __ry); + } else if (__t < __u) { + return strong_ordering::less; + } else if (__t > __u) { + return strong_ordering::greater; + } else if (__t == __u) { + if constexpr (numeric_limits<_Dp>::radix == 2) { + return _VSTD::signbit(__u) <=> _VSTD::signbit(__t); + } else { + // This is bullet 3 of the IEEE754 algorithm, relevant + // only for decimal floating-point; + // see https://stackoverflow.com/questions/69068075/ + if (__t == 0 || _VSTD::isinf(__t)) { + return _VSTD::signbit(__u) <=> _VSTD::signbit(__t); + } else { + int __texp, __uexp; + (void)_VSTD::frexp(__t, &__texp); + (void)_VSTD::frexp(__u, &__uexp); + return (__t < 0) ? (__texp <=> __uexp) : (__uexp <=> __texp); + } + } + } else { + // They're unordered, so one of them must be a NAN. + // The order is -QNAN, -SNAN, numbers, +SNAN, +QNAN. + bool __t_is_nan = _VSTD::isnan(__t); + bool __u_is_nan = _VSTD::isnan(__u); + bool __t_is_negative = _VSTD::signbit(__t); + bool __u_is_negative = _VSTD::signbit(__u); + using _IntType = conditional_t< + sizeof(__t) == sizeof(int32_t), int32_t, conditional_t< + sizeof(__t) == sizeof(int64_t), int64_t, void> + >; + if constexpr (is_same_v<_IntType, void>) { + static_assert(sizeof(_Dp) == 0, "std::strong_order is unimplemented for this floating-point type"); + } else if (__t_is_nan && __u_is_nan) { + // Order by sign bit, then by "payload bits" (we'll just use bit_cast). + if (__t_is_negative != __u_is_negative) { + return (__u_is_negative <=> __t_is_negative); + } else { + return _VSTD::bit_cast<_IntType>(__t) <=> _VSTD::bit_cast<_IntType>(__u); + } + } else if (__t_is_nan) { + return __t_is_negative ? strong_ordering::less : strong_ordering::greater; + } else { + return __u_is_negative ? strong_ordering::greater : strong_ordering::less; + } + } + } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return strong_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<2>()); } + }; +} // namespace __strong_order + +inline namespace __cpo { + inline constexpr auto strong_order = __strong_order::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___COMPARE_STRONG_ORDER diff --git a/lib/libcxx/include/__compare/synth_three_way.h b/lib/libcxx/include/__compare/synth_three_way.h new file mode 100644 index 0000000000..b93d4932c5 --- /dev/null +++ b/lib/libcxx/include/__compare/synth_three_way.h @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMPARE_SYNTH_THREE_WAY_H +#define _LIBCPP___COMPARE_SYNTH_THREE_WAY_H + +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/boolean_testable.h> +#include <__config> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [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; + } + }; + +template +using __synth_three_way_result = decltype(__synth_three_way(declval<_Tp&>(), declval<_Up&>())); + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_SYNTH_THREE_WAY_H diff --git a/lib/libcxx/include/__compare/three_way_comparable.h b/lib/libcxx/include/__compare/three_way_comparable.h new file mode 100644 index 0000000000..548bf17f0f --- /dev/null +++ b/lib/libcxx/include/__compare/three_way_comparable.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___COMPARE_THREE_WAY_COMPARABLE_H +#define _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H + +#include <__compare/common_comparison_category.h> +#include <__compare/ordering.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +concept __compares_as = + same_as, _Cat>; + +template +concept three_way_comparable = + __weakly_equality_comparable_with<_Tp, _Tp> && + __partially_ordered_with<_Tp, _Tp> && + requires(__make_const_lvalue_ref<_Tp> __a, __make_const_lvalue_ref<_Tp> __b) { + { __a <=> __b } -> __compares_as<_Cat>; + }; + +template +concept three_way_comparable_with = + three_way_comparable<_Tp, _Cat> && + three_way_comparable<_Up, _Cat> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + three_way_comparable, __make_const_lvalue_ref<_Up>>, _Cat> && + __weakly_equality_comparable_with<_Tp, _Up> && + __partially_ordered_with<_Tp, _Up> && + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t <=> __u } -> __compares_as<_Cat>; + { __u <=> __t } -> __compares_as<_Cat>; + }; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H diff --git a/lib/libcxx/include/__compare/weak_order.h b/lib/libcxx/include/__compare/weak_order.h new file mode 100644 index 0000000000..1286f39b02 --- /dev/null +++ b/lib/libcxx/include/__compare/weak_order.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___COMPARE_WEAK_ORDER +#define _LIBCPP___COMPARE_WEAK_ORDER + +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__compare/strong_order.h> +#include <__config> +#include <__utility/forward.h> +#include <__utility/priority_tag.h> +#include +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [cmp.alg] +namespace __weak_order { + struct __fn { + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<3>) + noexcept(noexcept(weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template> + requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> + _LIBCPP_HIDE_FROM_ABI static constexpr weak_ordering + __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) noexcept + { + partial_ordering __po = (__t <=> __u); + if (__po == partial_ordering::less) { + return weak_ordering::less; + } else if (__po == partial_ordering::equivalent) { + return weak_ordering::equivalent; + } else if (__po == partial_ordering::greater) { + return weak_ordering::greater; + } else { + // Otherwise, at least one of them is a NaN. + bool __t_is_nan = _VSTD::isnan(__t); + bool __u_is_nan = _VSTD::isnan(__u); + bool __t_is_negative = _VSTD::signbit(__t); + bool __u_is_negative = _VSTD::signbit(__u); + if (__t_is_nan && __u_is_nan) { + return (__u_is_negative <=> __t_is_negative); + } else if (__t_is_nan) { + return __t_is_negative ? weak_ordering::less : weak_ordering::greater; + } else { + return __u_is_negative ? weak_ordering::greater : weak_ordering::less; + } + } + } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) + noexcept(noexcept(weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(compare_three_way()(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + requires is_same_v, decay_t<_Up>> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) + noexcept(noexcept(weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) + -> decltype( weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) + { return weak_ordering(_VSTD::strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(__go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>()))) + -> decltype( __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>())) + { return __go(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u), __priority_tag<3>()); } + }; +} // namespace __weak_order + +inline namespace __cpo { + inline constexpr auto weak_order = __weak_order::__fn{}; +} // namespace __cpo + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_WEAK_ORDER diff --git a/lib/libcxx/include/__concepts/arithmetic.h b/lib/libcxx/include/__concepts/arithmetic.h new file mode 100644 index 0000000000..c2f94239a6 --- /dev/null +++ b/lib/libcxx/include/__concepts/arithmetic.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___CONCEPTS_ARITHMETIC_H +#define _LIBCPP___CONCEPTS_ARITHMETIC_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concepts.arithmetic], arithmetic concepts + +template +concept integral = is_integral_v<_Tp>; + +template +concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + +template +concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + +template +concept floating_point = is_floating_point_v<_Tp>; + +// Concept helpers for the internal type traits for the fundamental types. + +template +concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; +template +concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_ARITHMETIC_H diff --git a/lib/libcxx/include/__concepts/assignable.h b/lib/libcxx/include/__concepts/assignable.h new file mode 100644 index 0000000000..62f39f1c8c --- /dev/null +++ b/lib/libcxx/include/__concepts/assignable.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_ASSIGNABLE_H +#define _LIBCPP___CONCEPTS_ASSIGNABLE_H + +#include <__concepts/common_reference_with.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.assignable] + +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>; + }; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_ASSIGNABLE_H diff --git a/lib/libcxx/include/__concepts/boolean_testable.h b/lib/libcxx/include/__concepts/boolean_testable.h new file mode 100644 index 0000000000..c04c304291 --- /dev/null +++ b/lib/libcxx/include/__concepts/boolean_testable.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___CONCEPTS_BOOLEAN_TESTABLE_H +#define _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concepts.booleantestable] + +template +concept __boolean_testable_impl = convertible_to<_Tp, bool>; + +template +concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { + { !_VSTD::forward<_Tp>(__t) } -> __boolean_testable_impl; +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE_H diff --git a/lib/libcxx/include/__concepts/class_or_enum.h b/lib/libcxx/include/__concepts/class_or_enum.h new file mode 100644 index 0000000000..3d28a8ad98 --- /dev/null +++ b/lib/libcxx/include/__concepts/class_or_enum.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_CLASS_OR_ENUM_H +#define _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// Whether a type is a class type or enumeration type according to the Core wording. + +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 +template +concept __workaround_52970 = is_class_v<__uncvref_t<_Tp>> || is_union_v<__uncvref_t<_Tp>>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H diff --git a/lib/libcxx/include/__concepts/common_reference_with.h b/lib/libcxx/include/__concepts/common_reference_with.h new file mode 100644 index 0000000000..119d8fd8de --- /dev/null +++ b/lib/libcxx/include/__concepts/common_reference_with.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_COMMON_REFERENCE_WITH_H +#define _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H + +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.commonref] + +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>>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H diff --git a/lib/libcxx/include/__concepts/common_with.h b/lib/libcxx/include/__concepts/common_with.h new file mode 100644 index 0000000000..ecaa23b63b --- /dev/null +++ b/lib/libcxx/include/__concepts/common_with.h @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_COMMON_WITH_H +#define _LIBCPP___CONCEPTS_COMMON_WITH_H + +#include <__concepts/common_reference_with.h> +#include <__concepts/same_as.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.common] + +template +concept common_with = + same_as, common_type_t<_Up, _Tp>> && + requires { + static_cast>(declval<_Tp>()); + static_cast>(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>>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMMON_WITH_H diff --git a/lib/libcxx/include/__concepts/constructible.h b/lib/libcxx/include/__concepts/constructible.h new file mode 100644 index 0000000000..49986bb248 --- /dev/null +++ b/lib/libcxx/include/__concepts/constructible.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_CONSTRUCTIBLE_H +#define _LIBCPP___CONCEPTS_CONSTRUCTIBLE_H + +#include <__concepts/convertible_to.h> +#include <__concepts/destructible.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.constructible] +template +concept constructible_from = + destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + +// [concept.default.init] + +template +concept __default_initializable = requires { ::new _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>; + +// [concept.copyconstructible] +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; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CONSTRUCTIBLE_H diff --git a/lib/libcxx/include/__concepts/convertible_to.h b/lib/libcxx/include/__concepts/convertible_to.h new file mode 100644 index 0000000000..75f5da203c --- /dev/null +++ b/lib/libcxx/include/__concepts/convertible_to.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_CONVERTIBLE_TO_H +#define _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H + +#include <__config> +#include <__utility/declval.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.convertible] + +template +concept convertible_to = + is_convertible_v<_From, _To> && + requires { + static_cast<_To>(declval<_From>()); + }; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H diff --git a/lib/libcxx/include/__concepts/copyable.h b/lib/libcxx/include/__concepts/copyable.h new file mode 100644 index 0000000000..c264b31a21 --- /dev/null +++ b/lib/libcxx/include/__concepts/copyable.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_COPYABLE_H +#define _LIBCPP___CONCEPTS_COPYABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/constructible.h> +#include <__concepts/movable.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concepts.object] + +template +concept copyable = + copy_constructible<_Tp> && + movable<_Tp> && + assignable_from<_Tp&, _Tp&> && + assignable_from<_Tp&, const _Tp&> && + assignable_from<_Tp&, const _Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COPYABLE_H diff --git a/lib/libcxx/include/__concepts/derived_from.h b/lib/libcxx/include/__concepts/derived_from.h new file mode 100644 index 0000000000..acd4ba473c --- /dev/null +++ b/lib/libcxx/include/__concepts/derived_from.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___CONCEPTS_DERIVED_FROM_H +#define _LIBCPP___CONCEPTS_DERIVED_FROM_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.derived] + +template +concept derived_from = + is_base_of_v<_Bp, _Dp> && + is_convertible_v; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DERIVED_FROM_H diff --git a/lib/libcxx/include/__concepts/destructible.h b/lib/libcxx/include/__concepts/destructible.h new file mode 100644 index 0000000000..d57824be9e --- /dev/null +++ b/lib/libcxx/include/__concepts/destructible.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___CONCEPTS_DESTRUCTIBLE_H +#define _LIBCPP___CONCEPTS_DESTRUCTIBLE_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.destructible] + +template +concept destructible = is_nothrow_destructible_v<_Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DESTRUCTIBLE_H diff --git a/lib/libcxx/include/__concepts/different_from.h b/lib/libcxx/include/__concepts/different_from.h new file mode 100644 index 0000000000..c8560baf8a --- /dev/null +++ b/lib/libcxx/include/__concepts/different_from.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_DIFFERENT_FROM_H +#define _LIBCPP___CONCEPTS_DIFFERENT_FROM_H + +#include <__concepts/same_as.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +concept __different_from = !same_as, remove_cvref_t<_Up>>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_DIFFERENT_FROM_H diff --git a/lib/libcxx/include/__concepts/equality_comparable.h b/lib/libcxx/include/__concepts/equality_comparable.h new file mode 100644 index 0000000000..064143b894 --- /dev/null +++ b/lib/libcxx/include/__concepts/equality_comparable.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___CONCEPTS_EQUALITY_COMPARABLE_H +#define _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/common_reference_with.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.equalitycomparable] + +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; + }; + +template +concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; + +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>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE_H diff --git a/lib/libcxx/include/__concepts/invocable.h b/lib/libcxx/include/__concepts/invocable.h new file mode 100644 index 0000000000..e528258e35 --- /dev/null +++ b/lib/libcxx/include/__concepts/invocable.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___CONCEPTS_INVOCABLE_H +#define _LIBCPP___CONCEPTS_INVOCABLE_H + +#include <__config> +#include <__functional/invoke.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.invocable] + +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 +concept regular_invocable = invocable<_Fn, _Args...>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_INVOCABLE_H diff --git a/lib/libcxx/include/__concepts/movable.h b/lib/libcxx/include/__concepts/movable.h new file mode 100644 index 0000000000..fd8c2e7fa2 --- /dev/null +++ b/lib/libcxx/include/__concepts/movable.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_MOVABLE_H +#define _LIBCPP___CONCEPTS_MOVABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/constructible.h> +#include <__concepts/swappable.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concepts.object] + +template +concept movable = + is_object_v<_Tp> && + move_constructible<_Tp> && + assignable_from<_Tp&, _Tp> && + swappable<_Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_MOVABLE_H diff --git a/lib/libcxx/include/__concepts/predicate.h b/lib/libcxx/include/__concepts/predicate.h new file mode 100644 index 0000000000..491a7d6c73 --- /dev/null +++ b/lib/libcxx/include/__concepts/predicate.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___CONCEPTS_PREDICATE_H +#define _LIBCPP___CONCEPTS_PREDICATE_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/invocable.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.predicate] + +template +concept predicate = + regular_invocable<_Fn, _Args...> && __boolean_testable>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_PREDICATE_H diff --git a/lib/libcxx/include/__concepts/regular.h b/lib/libcxx/include/__concepts/regular.h new file mode 100644 index 0000000000..e8a87c97fe --- /dev/null +++ b/lib/libcxx/include/__concepts/regular.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_REGULAR_H +#define _LIBCPP___CONCEPTS_REGULAR_H + +#include <__concepts/equality_comparable.h> +#include <__concepts/semiregular.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.object] + +template +concept regular = semiregular<_Tp> && equality_comparable<_Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_REGULAR_H diff --git a/lib/libcxx/include/__concepts/relation.h b/lib/libcxx/include/__concepts/relation.h new file mode 100644 index 0000000000..fa7e5d17df --- /dev/null +++ b/lib/libcxx/include/__concepts/relation.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_RELATION_H +#define _LIBCPP___CONCEPTS_RELATION_H + +#include <__concepts/predicate.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.relation] + +template +concept relation = + predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && + predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; + +// [concept.equiv] + +template +concept equivalence_relation = relation<_Rp, _Tp, _Up>; + +// [concept.strictweakorder] + +template +concept strict_weak_order = relation<_Rp, _Tp, _Up>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_RELATION_H diff --git a/lib/libcxx/include/__concepts/same_as.h b/lib/libcxx/include/__concepts/same_as.h new file mode 100644 index 0000000000..ee86c44ea3 --- /dev/null +++ b/lib/libcxx/include/__concepts/same_as.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___CONCEPTS_SAME_AS_H +#define _LIBCPP___CONCEPTS_SAME_AS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.same] + +template +concept __same_as_impl = _IsSame<_Tp, _Up>::value; + +template +concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SAME_AS_H diff --git a/lib/libcxx/include/__concepts/semiregular.h b/lib/libcxx/include/__concepts/semiregular.h new file mode 100644 index 0000000000..4797fc7eaa --- /dev/null +++ b/lib/libcxx/include/__concepts/semiregular.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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___CONCEPTS_SEMIREGULAR_H +#define _LIBCPP___CONCEPTS_SEMIREGULAR_H + +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.object] + +template +concept semiregular = copyable<_Tp> && default_initializable<_Tp>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SEMIREGULAR_H diff --git a/lib/libcxx/include/__concepts/swappable.h b/lib/libcxx/include/__concepts/swappable.h new file mode 100644 index 0000000000..6b8cf82b70 --- /dev/null +++ b/lib/libcxx/include/__concepts/swappable.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___CONCEPTS_SWAPPABLE_H +#define _LIBCPP___CONCEPTS_SWAPPABLE_H + +#include <__concepts/assignable.h> +#include <__concepts/class_or_enum.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__utility/exchange.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.swappable] + +namespace ranges { +namespace __swap { + + template + void swap(_Tp&, _Tp&) = delete; + + 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)); + }; + + struct __fn; + + 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]); + }; + + 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)); + } + + // 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)); + } + }; +} // namespace __swap + +inline namespace __cpo { + inline constexpr auto swap = __swap::__fn{}; +} // namespace __cpo +} // namespace ranges + +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)); + }; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SWAPPABLE_H diff --git a/lib/libcxx/include/__concepts/totally_ordered.h b/lib/libcxx/include/__concepts/totally_ordered.h new file mode 100644 index 0000000000..58dcb42be5 --- /dev/null +++ b/lib/libcxx/include/__concepts/totally_ordered.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___CONCEPTS_TOTALLY_ORDERED_H +#define _LIBCPP___CONCEPTS_TOTALLY_ORDERED_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/equality_comparable.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [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 totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; + +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>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_TOTALLY_ORDERED_H diff --git a/lib/libcxx/include/__config b/lib/libcxx/include/__config index eae2b9ae30..458d0c1b89 100644 --- a/lib/libcxx/include/__config +++ b/lib/libcxx/include/__config @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------------- __config ---------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,6 +10,8 @@ #ifndef _LIBCPP_CONFIG #define _LIBCPP_CONFIG +#include <__config_site> + #if defined(_MSC_VER) && !defined(__clang__) # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER @@ -22,17 +24,7 @@ #ifdef __cplusplus -#ifdef __GNUC__ -# define _GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__) -// The _GNUC_VER_NEW macro better represents the new GCC versioning scheme -// introduced in GCC 5.0. -# define _GNUC_VER_NEW (_GNUC_VER * 10 + __GNUC_PATCHLEVEL__) -#else -# define _GNUC_VER 0 -# define _GNUC_VER_NEW 0 -#endif - -#define _LIBCPP_VERSION 13000 +#define _LIBCPP_VERSION 14000 #ifndef _LIBCPP_ABI_VERSION # define _LIBCPP_ABI_VERSION 1 @@ -82,14 +74,15 @@ # define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB # define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB # define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE -// Don't use a nullptr_t simulation type in C++03 instead using C++11 nullptr -// provided under the alternate keyword __nullptr, which changes the mangling -// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode. -# define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR // Define a key function for `bad_function_call` in the library, to centralize // its vtable and typeinfo to libc++ rather than having all other libraries // using that class define their own copies. # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +// Override the default return value of exception::what() for +// bad_function_call::what() with a string that is specific to +// bad_function_call (see http://wg21.link/LWG2233). This is an ABI break +// because it changes the vtable layout of bad_function_call. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE // Enable optimized version of __do_get_(un)signed which avoids redundant copies. # define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET // In C++20 and later, don't derive std::plus from std::binary_function, @@ -114,6 +107,17 @@ # define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI // Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr # define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI +// std::random_device holds some state when it uses an implementation that gets +// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this +// implementation to another one on a platform that has already shipped +// std::random_device, one needs to retain the same object layout to remain ABI +// compatible. This switch removes these workarounds for platforms that don't care +// about ABI compatibility. +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT +// Remove basic_string common base +# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON +// Remove vector base class +# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support @@ -125,16 +129,38 @@ # endif // Feature macros for disabling pre ABI v1 features. All of these options // are deprecated. -# if defined(__FreeBSD__) || defined(__DragonFly__) +# if defined(__FreeBSD__) # define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR # endif #endif +// By default, don't use a nullptr_t emulation type in C++03. +// +// This is technically an ABI break from previous releases, however it is +// very unlikely to impact anyone. If a user is impacted by this break, +// they can return to using the C++03 nullptr emulation by defining +// _LIBCPP_ABI_USE_CXX03_NULLPTR_EMULATION. +// +// This switch will be removed entirely in favour of never providing a +// C++03 emulation after one release. +// +// IMPORTANT: IF YOU ARE READING THIS AND YOU TURN THIS MACRO ON, PLEASE LEAVE +// A COMMENT ON https://reviews.llvm.org/D109459 OR YOU WILL BE BROKEN +// IN THE FUTURE WHEN WE REMOVE THE ABILITY TO USE THE C++03 EMULATION. +#ifndef _LIBCPP_ABI_USE_CXX03_NULLPTR_EMULATION +# define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR +#endif + #if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2 // Enable additional explicit instantiations of iostreams components. This // reduces the number of weak definitions generated in programs that use // iostreams by providing a single strong definition in the shared library. # define _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 + +// Define a key function for `bad_function_call` in the library, to centralize +// its vtable and typeinfo to libc++ rather than having all other libraries +// using that class define their own copies. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION #endif #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y @@ -235,6 +261,10 @@ # endif // defined(__GLIBC_PREREQ) #endif // defined(__linux__) +#if defined(__MVS__) +# include // for __NATIVE_ASCII_F +#endif + #ifdef __LITTLE_ENDIAN__ # if __LITTLE_ENDIAN__ # define _LIBCPP_LITTLE_ENDIAN @@ -263,9 +293,6 @@ # else // _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_BIG_ENDIAN # endif // _BYTE_ORDER == _LITTLE_ENDIAN -# ifndef __LONG_LONG_SUPPORTED -# define _LIBCPP_HAS_NO_LONG_LONG -# endif // __LONG_LONG_SUPPORTED #endif // __FreeBSD__ #if defined(__NetBSD__) || defined(__OpenBSD__) @@ -316,18 +343,56 @@ # endif #endif // __sun__ -#if defined(__OpenBSD__) || defined(__CloudABI__) - // Certain architectures provide arc4random(). Prefer using - // arc4random() over /dev/{u,}random to make it possible to obtain - // random data even when using sandboxing mechanisms such as chroots, - // Capsicum, etc. +#if defined(_AIX) && !defined(__64BIT__) + // The size of wchar is 2 byte on 32-bit mode on AIX. +# define _LIBCPP_SHORT_WCHAR 1 +#endif + +// Libc++ supports various implementations of std::random_device. +// +// _LIBCPP_USING_DEV_RANDOM +// Read entropy from the given file, by default `/dev/urandom`. +// If a token is provided, it is assumed to be the path to a file +// to read entropy from. This is the default behavior if nothing +// else is specified. This implementation requires storing state +// inside `std::random_device`. +// +// _LIBCPP_USING_ARC4_RANDOM +// Use arc4random(). This allows obtaining random data even when +// using sandboxing mechanisms. On some platforms like Apple, this +// is the recommended source of entropy for user-space programs. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_GETENTROPY +// Use getentropy(). +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_FUCHSIA_CPRNG +// Use Fuchsia's zx_cprng_draw() system call, which is specified to +// deliver high-quality entropy and cannot fail. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_NACL_RANDOM +// NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, +// including accesses to the special files under `/dev`. This implementation +// uses the NaCL syscall `nacl_secure_random_init()` to get entropy. +// When this option is used, the token passed to `std::random_device`'s +// constructor *must* be "/dev/urandom" -- anything else is an error. +// +// _LIBCPP_USING_WIN32_RANDOM +// Use rand_s(), for use on Windows. +// 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(__OpenBSD__) || defined(__APPLE__) # define _LIBCPP_USING_ARC4_RANDOM -#elif defined(__Fuchsia__) || defined(__wasi__) +#elif defined(__wasi__) # define _LIBCPP_USING_GETENTROPY +#elif defined(__Fuchsia__) +# define _LIBCPP_USING_FUCHSIA_CPRNG #elif defined(__native_client__) - // NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, - // including accesses to the special files under /dev. C++11's - // std::random_device is instead exposed through a NaCl syscall. # define _LIBCPP_USING_NACL_RANDOM #elif defined(_LIBCPP_WIN32API) # define _LIBCPP_USING_WIN32_RANDOM @@ -380,7 +445,7 @@ # if __ANDROID_API__ >= 29 # define _LIBCPP_HAS_TIMESPEC_GET # endif -# elif defined(__Fuchsia__) || defined(__wasi__) || defined(__NetBSD__) || defined(__DragonFly__) +# elif defined(__Fuchsia__) || defined(__wasi__) || defined(__NetBSD__) # define _LIBCPP_HAS_ALIGNED_ALLOC # define _LIBCPP_HAS_QUICK_EXIT # define _LIBCPP_HAS_TIMESPEC_GET @@ -490,14 +555,6 @@ typedef __char32_t char32_t; # define _LIBCPP_HAS_BLOCKS_RUNTIME #endif -#if !(__has_feature(cxx_relaxed_constexpr)) -#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#endif - -#if !(__has_feature(cxx_variable_templates)) -#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES -#endif - #if !(__has_feature(cxx_noexcept)) #define _LIBCPP_HAS_NO_NOEXCEPT #endif @@ -511,26 +568,8 @@ typedef __char32_t char32_t; #define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) #endif -#if __has_builtin(__builtin_launder) -#define _LIBCPP_COMPILER_HAS_BUILTIN_LAUNDER -#endif - -#if __has_builtin(__builtin_constant_p) -#define _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P -#endif - -#if !__is_identifier(__has_unique_object_representations) -#define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS -#endif - #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) -// Literal operators ""d and ""y are supported starting with LLVM Clang 8 and AppleClang 10.0.1 -#if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 800) || \ - (defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1001) -#define _LIBCPP_HAS_NO_CXX20_CHRONO_LITERALS -#endif - #define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ #elif defined(_LIBCPP_COMPILER_GCC) @@ -544,26 +583,10 @@ typedef __char32_t char32_t; # define _LIBCPP_NO_EXCEPTIONS #endif -// Determine if GCC supports relaxed constexpr -#if !defined(__cpp_constexpr) || __cpp_constexpr < 201304L -#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#endif - -// GCC 5 supports variable templates -#if !defined(__cpp_variable_templates) || __cpp_variable_templates < 201304L -#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES -#endif - #if !defined(__SANITIZE_ADDRESS__) #define _LIBCPP_HAS_NO_ASAN #endif -#if _GNUC_VER >= 700 -#define _LIBCPP_COMPILER_HAS_BUILTIN_LAUNDER -#define _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P -#define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS -#endif - #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) #define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ @@ -578,8 +601,6 @@ typedef __char32_t char32_t; #error "MSVC versions prior to Visual Studio 2015 are not supported" #endif -#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #define __alignof__ __alignof #define _LIBCPP_NORETURN __declspec(noreturn) #define _ALIGNAS(x) __declspec(align(x)) @@ -603,7 +624,6 @@ typedef __char32_t char32_t; #define _LIBCPP_NORETURN __attribute__((noreturn)) #define _LIBCPP_HAS_NO_UNICODE_CHARS -#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #if defined(_AIX) #define __MULTILOCALE_API @@ -803,10 +823,10 @@ typedef __char32_t char32_t; // Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE { #define _LIBCPP_END_NAMESPACE_STD } } -#define _VSTD std::_LIBCPP_ABI_NAMESPACE +#define _VSTD std _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 17 +#if _LIBCPP_STD_VER > 14 #define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { #else @@ -834,7 +854,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD #ifdef _LIBCPP_HAS_NO_UNICODE_CHARS typedef unsigned short char16_t; typedef unsigned int char32_t; -#endif // _LIBCPP_HAS_NO_UNICODE_CHARS +#endif #ifndef __SIZEOF_INT128__ #define _LIBCPP_HAS_NO_INT128 @@ -857,26 +877,10 @@ typedef unsigned int char32_t; # define _LIBCPP_CONSTEVAL consteval #endif -#if !defined(__cpp_concepts) || __cpp_concepts < 201907L +#if _LIBCPP_STD_VER <= 17 || !defined(__cpp_concepts) || __cpp_concepts < 201907L #define _LIBCPP_HAS_NO_CONCEPTS #endif -#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_HAS_NO_CONCEPTS) -#define _LIBCPP_HAS_NO_RANGES -#endif - -#ifdef _LIBCPP_CXX03_LANG -# define _LIBCPP_DEFAULT {} -#else -# define _LIBCPP_DEFAULT = default; -#endif - -#ifdef _LIBCPP_CXX03_LANG -# define _LIBCPP_EQUAL_DELETE -#else -# define _LIBCPP_EQUAL_DELETE = delete -#endif - #ifdef __GNUC__ # define _LIBCPP_NOALIAS __attribute__((__malloc__)) #else @@ -905,16 +909,35 @@ typedef unsigned int char32_t; // _LIBCPP_DEBUG potential values: // - undefined: No assertions. This is the default. // - 0: Basic assertions -// - 1: Basic assertions + iterator validity checks. -#if !defined(_LIBCPP_DEBUG) -# define _LIBCPP_DEBUG_LEVEL 0 -#elif _LIBCPP_DEBUG == 0 -# define _LIBCPP_DEBUG_LEVEL 1 -#elif _LIBCPP_DEBUG == 1 -# define _LIBCPP_DEBUG_LEVEL 2 -#else -# error Supported values for _LIBCPP_DEBUG are 0 and 1 -#endif +// - 1: Basic assertions + iterator validity checks + unspecified behavior randomization. +# if !defined(_LIBCPP_DEBUG) +# define _LIBCPP_DEBUG_LEVEL 0 +# elif _LIBCPP_DEBUG == 0 +# define _LIBCPP_DEBUG_LEVEL 1 +# elif _LIBCPP_DEBUG == 1 +# define _LIBCPP_DEBUG_LEVEL 2 +# else +# error Supported values for _LIBCPP_DEBUG are 0 and 1 +# endif + +# if _LIBCPP_DEBUG_LEVEL >= 2 && !defined(_LIBCPP_CXX03_LANG) +# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY +# endif + +# if defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) +# if defined(_LIBCPP_CXX03_LANG) +# error Support for unspecified stability is only for C++11 and higher +# endif +# define _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last) \ + do { \ + if (!__builtin_is_constant_evaluated()) \ + _VSTD::shuffle(__first, __last, __libcpp_debug_randomizer()); \ + } while (false) +# else +# define _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last) \ + do { \ + } while (false) +# endif // Libc++ allows disabling extern template instantiation declarations by // means of users defining _LIBCPP_DISABLE_EXTERN_TEMPLATE. @@ -938,11 +961,11 @@ typedef unsigned int char32_t; #endif #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || \ - defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__CloudABI__) + defined(__sun__) || defined(__NetBSD__) #define _LIBCPP_LOCALE__L_EXTENSIONS 1 #endif -#if defined(__FreeBSD__) || defined(__DragonFly__) +#ifdef __FreeBSD__ #define _DECLARE_C99_LDBL_MATH 1 #endif @@ -958,23 +981,16 @@ typedef unsigned int char32_t; # define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION #endif -#if defined(__APPLE__) -# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ - defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -# define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ -# endif -#endif // defined(__APPLE__) - #if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) || \ (!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606) # define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__APPLE__) || defined(__FreeBSD__) #define _LIBCPP_HAS_DEFAULTRUNELOCALE #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__sun__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) #define _LIBCPP_WCTYPE_IS_MASK #endif @@ -1047,64 +1063,50 @@ typedef unsigned int char32_t; # define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit #endif -#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#if _LIBCPP_STD_VER > 11 # define _LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr #else # define _LIBCPP_CONSTEXPR_AFTER_CXX11 #endif -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#if _LIBCPP_STD_VER > 14 # define _LIBCPP_CONSTEXPR_AFTER_CXX14 constexpr #else # define _LIBCPP_CONSTEXPR_AFTER_CXX14 #endif -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#if _LIBCPP_STD_VER > 17 # define _LIBCPP_CONSTEXPR_AFTER_CXX17 constexpr #else # define _LIBCPP_CONSTEXPR_AFTER_CXX17 #endif -// The _LIBCPP_NODISCARD_ATTRIBUTE should only be used to define other -// NODISCARD macros to the correct attribute. #if __has_cpp_attribute(nodiscard) || defined(_LIBCPP_COMPILER_MSVC) -# define _LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]] +# define _LIBCPP_NODISCARD [[nodiscard]] #elif defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(_LIBCPP_CXX03_LANG) -# define _LIBCPP_NODISCARD_ATTRIBUTE [[clang::warn_unused_result]] +# define _LIBCPP_NODISCARD [[clang::warn_unused_result]] #else // We can't use GCC's [[gnu::warn_unused_result]] and // __attribute__((warn_unused_result)), because GCC does not silence them via // (void) cast. -# define _LIBCPP_NODISCARD_ATTRIBUTE +# define _LIBCPP_NODISCARD #endif // _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not // specified as such as an extension. #if defined(_LIBCPP_ENABLE_NODISCARD) && !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD_ATTRIBUTE +# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD #else # define _LIBCPP_NODISCARD_EXT #endif #if !defined(_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17) && \ (_LIBCPP_STD_VER > 17 || defined(_LIBCPP_ENABLE_NODISCARD)) -# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD_ATTRIBUTE +# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD #else # define _LIBCPP_NODISCARD_AFTER_CXX17 #endif -#if _LIBCPP_STD_VER > 14 && defined(__cpp_inline_variables) && (__cpp_inline_variables >= 201606L) -# define _LIBCPP_INLINE_VAR inline -#else -# define _LIBCPP_INLINE_VAR -#endif - -#if defined(_LIBCPP_DEBUG) || defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) -# define _LIBCPP_CONSTEXPR_IF_NODEBUG -#else -# define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr -#endif - #if __has_attribute(no_destroy) # define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) #else @@ -1138,16 +1140,13 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( defined(__wasi__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) || \ - defined(__DragonFly__) || \ defined(__NuttX__) || \ defined(__linux__) || \ defined(__GNU__) || \ defined(__APPLE__) || \ - defined(__CloudABI__) || \ defined(__sun__) || \ defined(__MVS__) || \ - defined(_AIX) || \ - (defined(__MINGW32__) && __has_include()) + defined(_AIX) # define _LIBCPP_HAS_THREAD_API_PTHREAD # elif defined(__Fuchsia__) // TODO(44575): Switch to C11 thread API when possible. @@ -1217,21 +1216,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION #endif -// Systems that use capability-based security (FreeBSD with Capsicum, -// Nuxi CloudABI) may only provide local filesystem access (using *at()). -// Functions like open(), rename(), unlink() and stat() should not be -// used, as they attempt to access the global filesystem namespace. -#ifdef __CloudABI__ -#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE -#endif - -// CloudABI is intended for running networked services. Processes do not -// have standard input and output channels. -#ifdef __CloudABI__ -#define _LIBCPP_HAS_NO_STDIN -#define _LIBCPP_HAS_NO_STDOUT -#endif - // Some systems do not provide gets() in their C library, for security reasons. #if defined(_LIBCPP_MSVCRT) || \ (defined(__FreeBSD_version) && __FreeBSD_version >= 1300043) || \ @@ -1239,28 +1223,21 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # define _LIBCPP_C_HAS_NO_GETS #endif -#if defined(__BIONIC__) || defined(__CloudABI__) || defined(__NuttX__) || \ - defined(__Fuchsia__) || defined(__wasi__) || defined(_LIBCPP_HAS_MUSL_LIBC) || \ - defined(__MVS__) || defined(__OpenBSD__) +#if defined(__BIONIC__) || defined(__NuttX__) || \ + defined(__Fuchsia__) || defined(__wasi__) || \ + defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE #endif -// Thread-unsafe functions such as strtok() and localtime() -// are not available. -#ifdef __CloudABI__ -#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS -#endif - #if __has_feature(cxx_atomic) || __has_extension(c_atomic) || __has_keyword(_Atomic) # define _LIBCPP_HAS_C_ATOMIC_IMP #elif defined(_LIBCPP_COMPILER_GCC) # define _LIBCPP_HAS_GCC_ATOMIC_IMP #endif -#if (!defined(_LIBCPP_HAS_C_ATOMIC_IMP) && \ - !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) && \ - !defined(_LIBCPP_HAS_EXTERNAL_ATOMIC_IMP)) \ - || defined(_LIBCPP_HAS_NO_THREADS) +#if !defined(_LIBCPP_HAS_C_ATOMIC_IMP) && \ + !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) && \ + !defined(_LIBCPP_HAS_EXTERNAL_ATOMIC_IMP) # define _LIBCPP_HAS_NO_ATOMIC_HEADER #else # ifndef _LIBCPP_ATOMIC_FLAG_TYPE @@ -1279,8 +1256,9 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # if defined(__clang__) && __has_attribute(acquire_capability) // Work around the attribute handling in clang. When both __declspec and // __attribute__ are present, the processing goes awry preventing the definition -// of the types. -# if !defined(_LIBCPP_OBJECT_FORMAT_COFF) +// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus +// combining the two does work. +# if !defined(_MSC_VER) # define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS # endif # endif @@ -1298,14 +1276,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # define _LIBCPP_SAFE_STATIC #endif -#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700 -#define _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF -#endif - -#if !__has_builtin(__builtin_is_constant_evaluated) && _GNUC_VER < 900 -#define _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED -#endif - #if __has_attribute(diagnose_if) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) # define _LIBCPP_DIAGNOSE_WARNING(...) \ __attribute__((diagnose_if(__VA_ARGS__, "warning"))) @@ -1321,7 +1291,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # define _LIBCPP_FALLTHROUGH() [[fallthrough]] #elif __has_cpp_attribute(clang::fallthrough) # define _LIBCPP_FALLTHROUGH() [[clang::fallthrough]] -#elif __has_attribute(fallthrough) || _GNUC_VER >= 700 +#elif __has_attribute(__fallthrough__) # define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__)) #else # define _LIBCPP_FALLTHROUGH() ((void)0) @@ -1333,12 +1303,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( #define _LIBCPP_NODEBUG #endif -#if __has_attribute(__nodebug__) && (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 900) -# define _LIBCPP_NODEBUG_TYPE __attribute__((nodebug)) -#else -# define _LIBCPP_NODEBUG_TYPE -#endif - #if __has_attribute(__standalone_debug__) #define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) #else @@ -1351,6 +1315,16 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( #define _LIBCPP_PREFERRED_NAME(x) #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 +// impact on readability. +#if defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) +# define _LIBCPP_IF_WIDE_CHARACTERS(...) +#else +# define _LIBCPP_IF_WIDE_CHARACTERS(...) __VA_ARGS__ +#endif + #if defined(_LIBCPP_ABI_MICROSOFT) && \ (defined(_LIBCPP_COMPILER_MSVC) || __has_declspec_attribute(empty_bases)) # define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) @@ -1373,20 +1347,8 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( #define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS #endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES -#if !defined(__cpp_deduction_guides) || __cpp_deduction_guides < 201611 -#define _LIBCPP_HAS_NO_DEDUCTION_GUIDES -#endif - -#if !__has_keyword(__is_aggregate) && (_GNUC_VER_NEW < 7001) -#define _LIBCPP_HAS_NO_IS_AGGREGATE -#endif - -#if !defined(__cpp_coroutines) || __cpp_coroutines < 201703L -#define _LIBCPP_HAS_NO_COROUTINES -#endif - -#if !defined(__cpp_impl_three_way_comparison) || __cpp_impl_three_way_comparison < 201907L -#define _LIBCPP_HAS_NO_SPACESHIP_OPERATOR +#if !defined(__cpp_impl_coroutine) || __cpp_impl_coroutine < 201902L +#define _LIBCPP_HAS_NO_CXX20_COROUTINES #endif #if defined(_LIBCPP_COMPILER_IBM) @@ -1440,12 +1402,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # define _LIBCPP_FOPEN_CLOEXEC_MODE #endif -#ifdef _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P -#define _LIBCPP_BUILTIN_CONSTANT_P(x) __builtin_constant_p(x) -#else -#define _LIBCPP_BUILTIN_CONSTANT_P(x) false -#endif - // Support for _FILE_OFFSET_BITS=64 landed gradually in Android, so the full set // of functions used in cstdio may not be available for low API levels when // using 64-bit file offsets on LP32. @@ -1454,16 +1410,24 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( #endif #if __has_attribute(init_priority) -# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) + // TODO: Remove this once we drop support for building libc++ with old Clangs +# if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1200) || \ + (defined(__apple_build_version__) && __apple_build_version__ < 13000000) +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) +# else +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(100))) +# endif #else # define _LIBCPP_INIT_PRIORITY_MAX #endif #if defined(__GNUC__) || defined(__clang__) -#define _LIBCPP_FORMAT_PRINTF(a, b) \ - __attribute__((__format__(__printf__, a, b))) + // The attribute uses 1-based indices for ordinary and static member functions. + // The attribute uses 2-based indices for non-static member functions. +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \ + __attribute__((__format__(archetype, format_string_index, first_format_arg_index))) #else -#define _LIBCPP_FORMAT_PRINTF(a, b) +# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */ #endif #endif // __cplusplus diff --git a/lib/libcxx/include/__coroutine/coroutine_handle.h b/lib/libcxx/include/__coroutine/coroutine_handle.h new file mode 100644 index 0000000000..64657c0585 --- /dev/null +++ b/lib/libcxx/include/__coroutine/coroutine_handle.h @@ -0,0 +1,202 @@ +//===----------------------------------------------------------------------===// +// +// 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___COROUTINE_COROUTINE_HANDLE_H +#define _LIBCPP___COROUTINE_COROUTINE_HANDLE_H + +#include <__config> +#include <__debug> +#include <__functional/hash.h> +#include <__memory/addressof.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.handle] +template +struct _LIBCPP_TEMPLATE_VIS coroutine_handle; + +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 + constexpr coroutine_handle(nullptr_t) noexcept {} + + _LIBCPP_HIDE_FROM_ABI + coroutine_handle& operator=(nullptr_t) noexcept { + __handle_ = nullptr; + return *this; + } + + // [coroutine.handle.export.import], export/import + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + + _LIBCPP_HIDE_FROM_ABI + static constexpr coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + + // [coroutine.handle.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { + return __handle_ != nullptr; + } + + _LIBCPP_HIDE_FROM_ABI + bool done() const { + _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + return __builtin_coro_done(__handle_); + } + + // [coroutine.handle.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + void operator()() const { resume(); } + + _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"); + __builtin_coro_resume(__handle_); + } + + _LIBCPP_HIDE_FROM_ABI + void destroy() const { + _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + __builtin_coro_destroy(__handle_); + } + +private: + bool __is_suspended() const { + // FIXME actually implement a check for if the coro is suspended. + return __handle_ != nullptr; + } + + void* __handle_ = nullptr; +}; + +// [coroutine.handle.compare] +inline _LIBCPP_HIDE_FROM_ABI +constexpr bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return __x.address() == __y.address(); +} +inline _LIBCPP_HIDE_FROM_ABI +constexpr strong_ordering operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return compare_three_way()(__x.address(), __y.address()); +} + +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 + constexpr coroutine_handle(nullptr_t) noexcept {} + + _LIBCPP_HIDE_FROM_ABI + static coroutine_handle from_promise(_Promise& __promise) { + using _RawPromise = typename remove_cv<_Promise>::type; + coroutine_handle __tmp; + __tmp.__handle_ = + __builtin_coro_promise(_VSTD::addressof(const_cast<_RawPromise&>(__promise)), alignof(_Promise), true); + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + coroutine_handle& operator=(nullptr_t) noexcept { + __handle_ = nullptr; + return *this; + } + + // [coroutine.handle.export.import], export/import + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + + _LIBCPP_HIDE_FROM_ABI + static constexpr coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + + // [coroutine.handle.conv], conversion + _LIBCPP_HIDE_FROM_ABI + constexpr operator coroutine_handle<>() const noexcept { + return coroutine_handle<>::from_address(address()); + } + + // [coroutine.handle.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { + return __handle_ != nullptr; + } + + _LIBCPP_HIDE_FROM_ABI + bool done() const { + _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + return __builtin_coro_done(__handle_); + } + + // [coroutine.handle.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + void operator()() const { resume(); } + + _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"); + __builtin_coro_resume(__handle_); + } + + _LIBCPP_HIDE_FROM_ABI + void destroy() const { + _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + __builtin_coro_destroy(__handle_); + } + + // [coroutine.handle.promise], promise access + _LIBCPP_HIDE_FROM_ABI + _Promise& promise() const { + return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false)); + } + +private: + bool __is_suspended() const { + // FIXME actually implement a check for if the coro is suspended. + return __handle_ != nullptr; + } + void* __handle_ = nullptr; +}; + +// [coroutine.handle.hash] +template +struct hash> { + _LIBCPP_HIDE_FROM_ABI + size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept { return hash()(__v.address()); } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +#endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H diff --git a/lib/libcxx/include/__coroutine/coroutine_traits.h b/lib/libcxx/include/__coroutine/coroutine_traits.h new file mode 100644 index 0000000000..bfa69552bd --- /dev/null +++ b/lib/libcxx/include/__coroutine/coroutine_traits.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___COROUTINE_COROUTINE_TRAITS_H +#define _LIBCPP___COROUTINE_COROUTINE_TRAITS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.traits] +// [coroutine.traits.primary] +// The header defined the primary template coroutine_traits such that +// if ArgTypes is a parameter pack of types and if the qualified-id R::promise_type +// is valid and denotes a type ([temp.deduct]), then coroutine_traits +// has the following publicly accessible memebr: +// +// using promise_type = typename R::promise_type; +// +// Otherwise, coroutine_traits has no members. +template +struct __coroutine_traits_sfinae {}; + +template +struct __coroutine_traits_sfinae< + _Tp, typename __void_t::type> +{ + using promise_type = typename _Tp::promise_type; +}; + +template +struct coroutine_traits + : public __coroutine_traits_sfinae<_Ret> +{ +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +#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 new file mode 100644 index 0000000000..a29e202f4e --- /dev/null +++ b/lib/libcxx/include/__coroutine/noop_coroutine_handle.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___COROUTINE_NOOP_COROUTINE_HANDLE_H +#define _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H + +#include <__config> +#include <__coroutine/coroutine_handle.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) + +// [coroutine.noop] +// [coroutine.promise.noop] +struct noop_coroutine_promise {}; + +// [coroutine.handle.noop] +template <> +struct _LIBCPP_TEMPLATE_VIS coroutine_handle { +public: + // [coroutine.handle.noop.conv], conversion + _LIBCPP_HIDE_FROM_ABI + constexpr operator coroutine_handle<>() const noexcept { + return coroutine_handle<>::from_address(address()); + } + + // [coroutine.handle.noop.observers], observers + _LIBCPP_HIDE_FROM_ABI + constexpr explicit operator bool() const noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI + constexpr bool done() const noexcept { return false; } + + // [coroutine.handle.noop.resumption], resumption + _LIBCPP_HIDE_FROM_ABI + constexpr void operator()() const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void resume() const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void destroy() const noexcept {} + + // [coroutine.handle.noop.promise], promise access + _LIBCPP_HIDE_FROM_ABI + noop_coroutine_promise& promise() const noexcept { + return *static_cast( + __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false)); + } + + // [coroutine.handle.noop.address], address + _LIBCPP_HIDE_FROM_ABI + constexpr void* address() const noexcept { return __handle_; } + +private: + _LIBCPP_HIDE_FROM_ABI + friend coroutine_handle noop_coroutine() noexcept; + +#if __has_builtin(__builtin_coro_noop) + _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { + this->__handle_ = __builtin_coro_noop(); + } + + void* __handle_ = nullptr; + +#elif defined(_LIBCPP_COMPILER_GCC) + // GCC doesn't implement __builtin_coro_noop(). + // Construct the coroutine frame manually instead. + struct __noop_coroutine_frame_ty_ { + static void __dummy_resume_destroy_func() { } + + void (*__resume_)() = __dummy_resume_destroy_func; + void (*__destroy_)() = __dummy_resume_destroy_func; + struct noop_coroutine_promise __promise_; + }; + + static __noop_coroutine_frame_ty_ __noop_coroutine_frame_; + + void* __handle_ = &__noop_coroutine_frame_; + + _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default; + +#endif // __has_builtin(__builtin_coro_noop) +}; + +using noop_coroutine_handle = coroutine_handle; + +#if defined(_LIBCPP_COMPILER_GCC) +inline noop_coroutine_handle::__noop_coroutine_frame_ty_ + noop_coroutine_handle::__noop_coroutine_frame_{}; +#endif + +// [coroutine.noop.coroutine] +inline _LIBCPP_HIDE_FROM_ABI +noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); } + +#endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC) + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +#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 new file mode 100644 index 0000000000..c434f83b78 --- /dev/null +++ b/lib/libcxx/include/__coroutine/trivial_awaitables.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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___COROUTINE_TRIVIAL_AWAITABLES_H +#define __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H + +#include <__config> +#include <__coroutine/coroutine_handle.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [coroutine.trivial.awaitables] +struct suspend_never { + _LIBCPP_HIDE_FROM_ABI + constexpr bool await_ready() const noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void await_resume() const noexcept {} +}; + +struct suspend_always { + _LIBCPP_HIDE_FROM_ABI + constexpr bool await_ready() const noexcept { return false; } + _LIBCPP_HIDE_FROM_ABI + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_HIDE_FROM_ABI + constexpr void await_resume() const noexcept {} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // __LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_COROUTINES) + +#endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/lib/libcxx/include/__debug b/lib/libcxx/include/__debug index 771e431632..a1e21a7032 100644 --- a/lib/libcxx/include/__debug +++ b/lib/libcxx/include/__debug @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------------- __debug ----------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,6 +12,7 @@ #include <__config> #include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -22,9 +23,9 @@ #endif #if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY) -# include -# include # include +# include +# include #endif #if _LIBCPP_DEBUG_LEVEL == 0 @@ -34,7 +35,7 @@ # define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) # define _LIBCPP_ASSERT_IMPL(x, m) ((x) ? (void)0 : _VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, #x, m))) #elif _LIBCPP_DEBUG_LEVEL == 2 -# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(x, m) +# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(__libcpp_is_constant_evaluated() || (x), m) # define _LIBCPP_ASSERT_IMPL(x, m) ((x) ? (void)0 : _VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, #x, m))) #else # error _LIBCPP_DEBUG_LEVEL must be one of 0, 1, 2 @@ -268,6 +269,26 @@ _LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); #endif // _LIBCPP_DEBUG_LEVEL == 2 || defined(_LIBCPP_BUILDING_LIBRARY) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_c(_Tp* __c) { +#if _LIBCPP_DEBUG_LEVEL == 2 + if (!__libcpp_is_constant_evaluated()) + __get_db()->__insert_c(__c); +#else + (void)(__c); +#endif +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_i(_Tp* __i) { +#if _LIBCPP_DEBUG_LEVEL == 2 + if (!__libcpp_is_constant_evaluated()) + __get_db()->__insert_i(__i); +#else + (void)(__i); +#endif +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_DEBUG_H diff --git a/lib/libcxx/include/__errc b/lib/libcxx/include/__errc index 81da2e1970..68d5fa3201 100644 --- a/lib/libcxx/include/__errc +++ b/lib/libcxx/include/__errc @@ -1,5 +1,5 @@ // -*- C++ -*- -//===---------------------------- __errc ----------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libcxx/include/__filesystem/copy_options.h b/lib/libcxx/include/__filesystem/copy_options.h new file mode 100644 index 0000000000..c0140d4571 --- /dev/null +++ b/lib/libcxx/include/__filesystem/copy_options.h @@ -0,0 +1,80 @@ +// -*- 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___FILESYSTEM_COPY_OPTIONS_H +#define _LIBCPP___FILESYSTEM_COPY_OPTIONS_H + +#include <__availability> +#include <__config> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { + none = 0, + skip_existing = 1, + overwrite_existing = 2, + update_existing = 4, + recursive = 8, + copy_symlinks = 16, + skip_symlinks = 32, + directories_only = 64, + create_symlinks = 128, + create_hard_links = 256, + __in_recursive_copy = 512, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator~(copy_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +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 + +#endif // _LIBCPP___FILESYSTEM_COPY_OPTIONS_H diff --git a/lib/libcxx/include/__filesystem/directory_entry.h b/lib/libcxx/include/__filesystem/directory_entry.h new file mode 100644 index 0000000000..95e45c0230 --- /dev/null +++ b/lib/libcxx/include/__filesystem/directory_entry.h @@ -0,0 +1,511 @@ +// -*- 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___FILESYSTEM_DIRECTORY_ENTRY_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H + +#include <__availability> +#include <__config> +#include <__errc> +#include <__filesystem/file_status.h> +#include <__filesystem/file_time_type.h> +#include <__filesystem/file_type.h> +#include <__filesystem/filesystem_error.h> +#include <__filesystem/operations.h> +#include <__filesystem/path.h> +#include <__filesystem/perms.h> +#include +#include +#include +#include +#include + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_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_INLINE_VISIBILITY + explicit directory_entry(_Path const& __p) : __p_(__p) { + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { + __refresh(&__ec); + } + + ~directory_entry() {} + + directory_entry& operator=(directory_entry const&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p) { + __p_ = __p; + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p, error_code& __ec) { + __p_ = __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p) { + __p_.replace_filename(__p); + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p, error_code& __ec) { + __p_ = __p_.parent_path() / __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void refresh() { __refresh(); } + + _LIBCPP_INLINE_VISIBILITY + void refresh(error_code& __ec) noexcept { __refresh(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + _Path const& path() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + operator const _Path&() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool exists(error_code& __ec) const noexcept { + return _VSTD_FS::exists(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file() const { return __get_ft() == file_type::block; } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::block; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file() const { return __get_ft() == file_type::character; } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::character; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory() const { return __get_ft() == file_type::directory; } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::directory; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo() const { return __get_ft() == file_type::fifo; } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::fifo; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool is_other(error_code& __ec) const noexcept { + return _VSTD_FS::is_other(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file() const { return __get_ft() == file_type::regular; } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::regular; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket() const { return __get_ft() == file_type::socket; } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::socket; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink() const { return __get_sym_ft() == file_type::symlink; } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink(error_code& __ec) const noexcept { + return __get_sym_ft(&__ec) == file_type::symlink; + } + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size() const { return __get_size(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size(error_code& __ec) const noexcept { + return __get_size(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count() const { return __get_nlink(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count(error_code& __ec) const noexcept { + return __get_nlink(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time() const { return __get_write_time(); } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time(error_code& __ec) const noexcept { + return __get_write_time(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status status() const { return __get_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status status(error_code& __ec) const noexcept { + return __get_status(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status() const { return __get_symlink_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status(error_code& __ec) const noexcept { + return __get_symlink_status(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<(directory_entry const& __rhs) const noexcept { + return __p_ < __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator==(directory_entry const& __rhs) const noexcept { + return __p_ == __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator!=(directory_entry const& __rhs) const noexcept { + return __p_ != __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<=(directory_entry const& __rhs) const noexcept { + return __p_ <= __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>(directory_entry const& __rhs) const noexcept { + return __p_ > __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>=(directory_entry const& __rhs) const noexcept { + return __p_ >= __rhs.__p_; + } + + template + _LIBCPP_INLINE_VISIBILITY + friend basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) { + return __os << __d.path(); + } + +private: + friend class directory_iterator; + friend class recursive_directory_iterator; + friend class _LIBCPP_HIDDEN __dir_stream; + + enum _CacheType : unsigned char { + _Empty, + _IterSymlink, + _IterNonSymlink, + _RefreshSymlink, + _RefreshSymlinkUnresolved, + _RefreshNonSymlink + }; + + struct __cached_data { + uintmax_t __size_; + uintmax_t __nlink_; + file_time_type __write_time_; + perms __sym_perms_; + perms __non_sym_perms_; + file_type __type_; + _CacheType __cache_type_; + + _LIBCPP_INLINE_VISIBILITY + __cached_data() noexcept { __reset(); } + + _LIBCPP_INLINE_VISIBILITY + void __reset() { + __cache_type_ = _Empty; + __type_ = file_type::none; + __sym_perms_ = __non_sym_perms_ = perms::unknown; + __size_ = __nlink_ = uintmax_t(-1); + __write_time_ = file_time_type::min(); + } + }; + + _LIBCPP_INLINE_VISIBILITY + static __cached_data __create_iter_result(file_type __ft) { + __cached_data __data; + __data.__type_ = __ft; + __data.__cache_type_ = [&]() { + switch (__ft) { + case file_type::none: + return _Empty; + case file_type::symlink: + return _IterSymlink; + default: + return _IterNonSymlink; + } + }(); + return __data; + } + + _LIBCPP_INLINE_VISIBILITY + void __assign_iter_entry(_Path&& __p, __cached_data __dt) { + __p_ = _VSTD::move(__p); + __data_ = __dt; + } + + _LIBCPP_FUNC_VIS + error_code __do_refresh() noexcept; + + _LIBCPP_INLINE_VISIBILITY + static bool __is_dne_error(error_code const& __ec) { + if (!__ec) + return true; + switch (static_cast(__ec.value())) { + case errc::no_such_file_or_directory: + case errc::not_a_directory: + return true; + default: + return false; + } + } + + _LIBCPP_INLINE_VISIBILITY + void __handle_error(const char* __msg, error_code* __dest_ec, + error_code const& __ec, bool __allow_dne = false) const { + if (__dest_ec) { + *__dest_ec = __ec; + return; + } + if (__ec && (!__allow_dne || !__is_dne_error(__ec))) + __throw_filesystem_error(__msg, __p_, __ec); + } + + _LIBCPP_INLINE_VISIBILITY + void __refresh(error_code* __ec = nullptr) { + __handle_error("in directory_entry::refresh", __ec, __do_refresh(), + /*allow_dne*/ true); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_sym_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + return __symlink_status(__p_, __ec).type(); + case _IterSymlink: + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + if (__ec) + __ec->clear(); + return file_type::symlink; + case _IterNonSymlink: + case _RefreshNonSymlink: + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec).type(); + case _IterNonSymlink: + case _RefreshNonSymlink: + case _RefreshSymlink: { + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec); + case _RefreshNonSymlink: + case _RefreshSymlink: + return file_status(__get_ft(__ec), __data_.__non_sym_perms_); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_symlink_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + return __symlink_status(__p_, __ec); + case _RefreshNonSymlink: + return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_); + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_size(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__file_size(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::file_size", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { + errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory + : errc::not_supported; + __handle_error("in directory_entry::file_size", __ec, + make_error_code(__err_kind)); + } + return __data_.__size_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_nlink(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__hard_link_count(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + (void)__get_ft(&__m_ec); + __handle_error("in directory_entry::hard_link_count", __ec, __m_ec); + return __data_.__nlink_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type __get_write_time(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__last_write_time(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::last_write_time", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && + __data_.__write_time_ == file_time_type::min()) + __handle_error("in directory_entry::last_write_time", __ec, + make_error_code(errc::value_too_large)); + return __data_.__write_time_; + } + } + _LIBCPP_UNREACHABLE(); + } + +private: + _Path __p_; + __cached_data __data_; +}; + +class __dir_element_proxy { +public: + inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() { + return _VSTD::move(__elem_); + } + +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) + : __elem_(_VSTD::move(__o.__elem_)) {} + directory_entry __elem_; +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H diff --git a/lib/libcxx/include/__filesystem/directory_iterator.h b/lib/libcxx/include/__filesystem/directory_iterator.h new file mode 100644 index 0000000000..cfaf2064be --- /dev/null +++ b/lib/libcxx/include/__filesystem/directory_iterator.h @@ -0,0 +1,150 @@ +// -*- 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___FILESYSTEM_DIRECTORY_ITERATOR_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H + +#include <__availability> +#include <__config> +#include <__debug> +#include <__filesystem/directory_entry.h> +#include <__filesystem/directory_options.h> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include <__memory/shared_ptr.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/enable_view.h> +#include +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_HIDDEN __dir_stream; +class directory_iterator { +public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef value_type const* pointer; + typedef value_type const& reference; + typedef input_iterator_tag iterator_category; + +public: + //ctor & dtor + directory_iterator() noexcept {} + + explicit directory_iterator(const path& __p) + : directory_iterator(__p, nullptr) {} + + directory_iterator(const path& __p, directory_options __opts) + : directory_iterator(__p, nullptr, __opts) {} + + directory_iterator(const path& __p, error_code& __ec) + : directory_iterator(__p, &__ec) {} + + directory_iterator(const path& __p, directory_options __opts, + error_code& __ec) + : directory_iterator(__p, &__ec, __opts) {} + + directory_iterator(const directory_iterator&) = default; + directory_iterator(directory_iterator&&) = default; + directory_iterator& operator=(const directory_iterator&) = default; + + directory_iterator& operator=(directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + } + return *this; + } + + ~directory_iterator() = default; + + const directory_entry& operator*() const { + _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); + return __dereference(); + } + + const directory_entry* operator->() const { return &**this; } + + directory_iterator& operator++() { return __increment(); } + + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + directory_iterator& increment(error_code& __ec) { return __increment(&__ec); } + +private: + inline _LIBCPP_INLINE_VISIBILITY 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_FUNC_VIS + directory_iterator& __increment(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + const directory_entry& __dereference() const; + +private: + shared_ptr<__dir_stream> __imp_; +}; + +inline _LIBCPP_INLINE_VISIBILITY bool +operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +inline _LIBCPP_INLINE_VISIBILITY bool +operator!=(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} + +// enable directory_iterator range-based for statements +inline _LIBCPP_INLINE_VISIBILITY directory_iterator +begin(directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_INLINE_VISIBILITY directory_iterator +end(directory_iterator) noexcept { + return directory_iterator(); +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true; + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H diff --git a/lib/libcxx/include/__filesystem/directory_options.h b/lib/libcxx/include/__filesystem/directory_options.h new file mode 100644 index 0000000000..79c0c2cbaa --- /dev/null +++ b/lib/libcxx/include/__filesystem/directory_options.h @@ -0,0 +1,78 @@ +// -*- 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___FILESYSTEM_DIRECTORY_OPTIONS_H +#define _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H + +#include <__availability> +#include <__config> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { + none = 0, + follow_directory_symlink = 1, + skip_permission_denied = 2 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator&(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator|(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator^(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator~(directory_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator&=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator|=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator^=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS ^ _RHS; +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H diff --git a/lib/libcxx/include/__filesystem/file_status.h b/lib/libcxx/include/__filesystem/file_status.h new file mode 100644 index 0000000000..a8f653ab44 --- /dev/null +++ b/lib/libcxx/include/__filesystem/file_status.h @@ -0,0 +1,68 @@ +// -*- 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___FILESYSTEM_FILE_STATUS_H +#define _LIBCPP___FILESYSTEM_FILE_STATUS_H + +#include <__availability> +#include <__config> +#include <__filesystem/file_type.h> +#include <__filesystem/perms.h> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_TYPE_VIS file_status { +public: + // constructors + _LIBCPP_INLINE_VISIBILITY + file_status() noexcept : file_status(file_type::none) {} + _LIBCPP_INLINE_VISIBILITY + explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept + : __ft_(__ft), + __prms_(__prms) {} + + file_status(const file_status&) noexcept = default; + 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; + + // observers + _LIBCPP_INLINE_VISIBILITY + file_type type() const noexcept { return __ft_; } + + _LIBCPP_INLINE_VISIBILITY + perms permissions() const noexcept { return __prms_; } + + // modifiers + _LIBCPP_INLINE_VISIBILITY + void type(file_type __ft) noexcept { __ft_ = __ft; } + + _LIBCPP_INLINE_VISIBILITY + void permissions(perms __p) noexcept { __prms_ = __p; } + +private: + file_type __ft_; + perms __prms_; +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_STATUS_H diff --git a/lib/libcxx/include/__filesystem/file_time_type.h b/lib/libcxx/include/__filesystem/file_time_type.h new file mode 100644 index 0000000000..590146a066 --- /dev/null +++ b/lib/libcxx/include/__filesystem/file_time_type.h @@ -0,0 +1,27 @@ +// -*- 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___FILESYSTEM_FILE_TIME_TYPE_H +#define _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H + +#include <__availability> +#include <__config> +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +typedef chrono::time_point<_FilesystemClock> file_time_type; + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H diff --git a/lib/libcxx/include/__filesystem/file_type.h b/lib/libcxx/include/__filesystem/file_type.h new file mode 100644 index 0000000000..93bee86ad6 --- /dev/null +++ b/lib/libcxx/include/__filesystem/file_type.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 _LIBCPP___FILESYSTEM_FILE_TYPE_H +#define _LIBCPP___FILESYSTEM_FILE_TYPE_H + +#include <__availability> +#include <__config> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +// On Windows, the library never identifies files as block, character, fifo +// or socket. +enum class _LIBCPP_ENUM_VIS file_type : signed char { + none = 0, + not_found = -1, + regular = 1, + directory = 2, + symlink = 3, + block = 4, + character = 5, + fifo = 6, + socket = 7, + unknown = 8 +}; + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILE_TYPE_H diff --git a/lib/libcxx/include/__filesystem/filesystem_error.h b/lib/libcxx/include/__filesystem/filesystem_error.h new file mode 100644 index 0000000000..0b1874b0e5 --- /dev/null +++ b/lib/libcxx/include/__filesystem/filesystem_error.h @@ -0,0 +1,99 @@ +// -*- 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___FILESYSTEM_FILESYSTEM_ERROR_H +#define _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H + +#include <__availability> +#include <__config> +#include <__filesystem/path.h> +#include <__memory/shared_ptr.h> +#include +#include +#include +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_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())) { + __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())) { + __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)) { + __create_what(2); + } + + _LIBCPP_INLINE_VISIBILITY + const path& path1() const noexcept { return __storage_->__p1_; } + + _LIBCPP_INLINE_VISIBILITY + const path& path2() const noexcept { return __storage_->__p2_; } + + filesystem_error(const filesystem_error&) = default; + ~filesystem_error() override; // key function + + _LIBCPP_INLINE_VISIBILITY + 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) {} + + path __p1_; + path __p2_; + string __what_; + }; + 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 + +template +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_NO_EXCEPTIONS +void __throw_filesystem_error(_Args&&... __args) { + throw filesystem_error(_VSTD::forward<_Args>(__args)...); +} +#else +void __throw_filesystem_error(_Args&&...) { + _VSTD::abort(); +} +#endif +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H diff --git a/lib/libcxx/include/__filesystem/operations.h b/lib/libcxx/include/__filesystem/operations.h new file mode 100644 index 0000000000..918b4f9362 --- /dev/null +++ b/lib/libcxx/include/__filesystem/operations.h @@ -0,0 +1,197 @@ +// -*- 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___FILESYSTEM_OPERATIONS_H +#define _LIBCPP___FILESYSTEM_OPERATIONS_H + +#include <__availability> +#include <__config> +#include <__filesystem/copy_options.h> +#include <__filesystem/file_status.h> +#include <__filesystem/file_time_type.h> +#include <__filesystem/file_type.h> +#include <__filesystem/path.h> +#include <__filesystem/perm_options.h> +#include <__filesystem/perms.h> +#include <__filesystem/space_info.h> +#include +#include +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_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& p, error_code* ec = 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& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS bool __create_directory(const path& p, const path& attributes, error_code* ec = 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& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS void __last_write_time(const path& p, 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& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS uintmax_t __remove_all(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS bool __remove(const path& p, 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& p, uintmax_t size, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS path __temp_directory_path(error_code* __ec = nullptr); + +inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) { return __absolute(__p); } +inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p, error_code& __ec) { return __absolute(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) { return __canonical(__p); } +inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p, error_code& __ec) { return __canonical(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, const path& __to) { return __copy_file(__from, __to, copy_options::none); } +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, const path& __to, error_code& __ec) { return __copy_file(__from, __to, copy_options::none, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, const path& __to, copy_options __opt) { return __copy_file(__from, __to, __opt); } +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, const path& __to, copy_options __opt, error_code& __ec) { return __copy_file(__from, __to, __opt, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __from, const path& __to) { __copy_symlink(__from, __to); } +inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __from, const path& __to, error_code& __ec) noexcept { __copy_symlink(__from, __to, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to) { __copy(__from, __to, copy_options::none); } +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, error_code& __ec) { __copy(__from, __to, copy_options::none, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, copy_options __opt) { __copy(__from, __to, __opt); } +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, copy_options __opt, error_code& __ec) { __copy(__from, __to, __opt, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) { return __create_directories(__p); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p, error_code& __ec) { return __create_directories(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void create_directory_symlink(const path& __target, const path& __link) { __create_directory_symlink(__target, __link); } +inline _LIBCPP_INLINE_VISIBILITY void create_directory_symlink(const path& __target, const path& __link, error_code& __ec) noexcept { __create_directory_symlink(__target, __link, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) { return __create_directory(__p); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p, error_code& __ec) noexcept { return __create_directory(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p, const path& __attrs) { return __create_directory(__p, __attrs); } +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p, const path& __attrs, error_code& __ec) noexcept { return __create_directory(__p, __attrs, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __target, const path& __link) { __create_hard_link(__target, __link); } +inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __target, const path& __link, error_code& __ec) noexcept { __create_hard_link(__target, __link, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __target, const path& __link) { __create_symlink(__target, __link); } +inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __target, const path& __link, error_code& __ec) noexcept { return __create_symlink(__target, __link, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY path current_path() { return __current_path(); } +inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) { return __current_path(&__ec); } +inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) { __current_path(__p); } +inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p, error_code& __ec) noexcept { __current_path(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1, const path& __p2) { return __equivalent(__p1, __p2); } +inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept { return __equivalent(__p1, __p2, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept { return __s.type() != file_type::none; } +inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept { return status_known(__s) && __s.type() != file_type::not_found; } +inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) { return exists(__status(__p)); } + +inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p, error_code& __ec) noexcept { + auto __s = __status(__p, &__ec); + if (status_known(__s)) + __ec.clear(); + return exists(__s); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) { return __file_size(__p); } +inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p, error_code& __ec) noexcept { return __file_size(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) { return __hard_link_count(__p); } +inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept { return __hard_link_count(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept { return __s.type() == file_type::block; } +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) { return is_block_file(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p, error_code& __ec) noexcept { return is_block_file(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(file_status __s) noexcept { return __s.type() == file_type::character; } +inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) { return is_character_file(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p, error_code& __ec) noexcept { return is_character_file(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept { return __s.type() == file_type::directory; } +inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) { return is_directory(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY 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); +inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) { return __fs_is_empty(__p); } +inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p, error_code& __ec) { return __fs_is_empty(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; } +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) { return is_fifo(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p, error_code& __ec) noexcept { return is_fifo(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(file_status __s) noexcept { return __s.type() == file_type::regular; } +inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) { return is_regular_file(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p, error_code& __ec) noexcept { return is_regular_file(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept { return __s.type() == file_type::symlink; } +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) { return is_symlink(__symlink_status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p, error_code& __ec) noexcept { return is_symlink(__symlink_status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept { return exists(__s) && !is_regular_file(__s) && !is_directory(__s) && !is_symlink(__s); } +inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) { return is_other(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p, error_code& __ec) noexcept { return is_other(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept { return __s.type() == file_type::socket; } +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) { return is_socket(__status(__p)); } +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p, error_code& __ec) noexcept { return is_socket(__status(__p, &__ec)); } +inline _LIBCPP_INLINE_VISIBILITY file_time_type last_write_time(const path& __p) { return __last_write_time(__p); } +inline _LIBCPP_INLINE_VISIBILITY file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { return __last_write_time(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p, file_time_type __t) { __last_write_time(__p, __t); } +inline _LIBCPP_INLINE_VISIBILITY 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); +inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms, perm_options __opts = perm_options::replace) { __permissions(__p, __prms, __opts); } +inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { __permissions(__p, __prms, perm_options::replace, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms, perm_options __opts, error_code& __ec) { __permissions(__p, __prms, __opts, &__ec); } + +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return {}; + path __tmp_base = __weakly_canonical(__base, &__ec); + if (__ec) + return {}; + return __tmp.lexically_proximate(__tmp_base); +} + +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, error_code& __ec) { return proximate(__p, current_path(), __ec); } +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, const path& __base = current_path()) { return __weakly_canonical(__p).lexically_proximate(__weakly_canonical(__base)); } +inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) { return __read_symlink(__p); } +inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p, error_code& __ec) { return __read_symlink(__p, &__ec); } + +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return path(); + path __tmpbase = __weakly_canonical(__base, &__ec); + if (__ec) + return path(); + return __tmp.lexically_relative(__tmpbase); +} + +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, error_code& __ec) { return relative(__p, current_path(), __ec); } +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, const path& __base = current_path()) { return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base)); } +inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) { return __remove_all(__p); } +inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p, error_code& __ec) { return __remove_all(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) { return __remove(__p); } +inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p, error_code& __ec) noexcept { return __remove(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from, const path& __to) { return __rename(__from, __to); } +inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from, const path& __to, error_code& __ec) noexcept { return __rename(__from, __to, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p, uintmax_t __ns) { return __resize_file(__p, __ns); } +inline _LIBCPP_INLINE_VISIBILITY 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); +inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) { return __space(__p); } +inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p, error_code& __ec) noexcept { return __space(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) { return __status(__p); } +inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p, error_code& __ec) noexcept { return __status(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) { return __symlink_status(__p); } +inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p, error_code& __ec) noexcept { return __symlink_status(__p, &__ec); } +inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() { return __temp_directory_path(); } +inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) { return __temp_directory_path(&__ec); } +inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) { return __weakly_canonical(__p); } +inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p, error_code& __ec) { return __weakly_canonical(__p, &__ec); } + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_OPERATIONS_H diff --git a/lib/libcxx/include/__filesystem/path.h b/lib/libcxx/include/__filesystem/path.h new file mode 100644 index 0000000000..77547cbacb --- /dev/null +++ b/lib/libcxx/include/__filesystem/path.h @@ -0,0 +1,1018 @@ +// -*- 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___FILESYSTEM_PATH_H +#define _LIBCPP___FILESYSTEM_PATH_H + +#include <__availability> +#include <__config> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/iterator_traits.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include // for quoted +# include +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +template +struct __can_convert_char { + static const bool value = false; +}; +template +struct __can_convert_char : public __can_convert_char<_Tp> {}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = wchar_t; +}; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char8_t; +}; +#endif +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char16_t; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char32_t; +}; + +template +typename enable_if<__can_convert_char<_ECharT>::value, bool>::type +__is_separator(_ECharT __e) { +#if defined(_LIBCPP_WIN32API) + return __e == _ECharT('/') || __e == _ECharT('\\'); +#else + return __e == _ECharT('/'); +#endif +} + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +typedef u8string __u8_string; +#else +typedef string __u8_string; +#endif + +struct _NullSentinel {}; + +template +using _Void = void; + +template +struct __is_pathable_string : public false_type {}; + +template +struct __is_pathable_string< + basic_string<_ECharT, _Traits, _Alloc>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string<_ECharT, _Traits, _Alloc>; + using _Base = __can_convert_char<_ECharT>; + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template +struct __is_pathable_string< + basic_string_view<_ECharT, _Traits>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string_view<_ECharT, _Traits>; + using _Base = __can_convert_char<_ECharT>; + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template ::type, + class _UnqualPtrType = + typename remove_const::type>::type, + bool _IsCharPtr = is_pointer<_DS>::value&& + __can_convert_char<_UnqualPtrType>::value> +struct __is_pathable_char_array : false_type {}; + +template +struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> + : __can_convert_char::type> { + using _Base = __can_convert_char::type>; + + static _ECharT const* __range_begin(const _ECharT* __b) { return __b; } + static _ECharT const* __range_end(const _ECharT* __b) { + using _Iter = const _ECharT*; + const _ECharT __sentinel = _ECharT{}; + _Iter __e = __b; + for (; *__e != __sentinel; ++__e) + ; + return __e; + } + + static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } +}; + +template ::value, + class = void> +struct __is_pathable_iter : false_type {}; + +template +struct __is_pathable_iter< + _Iter, true, + _Void::value_type>::__char_type> > + : __can_convert_char::value_type> { + using _ECharT = typename iterator_traits<_Iter>::value_type; + using _Base = __can_convert_char<_ECharT>; + + static _Iter __range_begin(_Iter __b) { return __b; } + static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; } + + static _ECharT __first_or_null(_Iter __b) { return *__b; } +}; + +template ::value, + bool _IsCharIterT = __is_pathable_char_array<_Tp>::value, + bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value> +struct __is_pathable : false_type { + static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false"); +}; + +template +struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {}; + +template +struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> { +}; + +template +struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {}; + +#if defined(_LIBCPP_WIN32API) +typedef wstring __path_string; +typedef wchar_t __path_value; +#else +typedef string __path_string; +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); +#endif + +template +struct _PathCVT; + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) +template +struct _PathCVT { + static_assert(__can_convert_char<_ECharT>::value, + "Char type not convertible"); + + typedef __narrow_to_utf8 _Narrower; +#if defined(_LIBCPP_WIN32API) + typedef __widen_from_utf8 _Widener; +#endif + + static void __append_range(__path_string& __dest, _ECharT const* __b, + _ECharT const* __e) { +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __b, __e); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __b, __e); +#endif + } + + template + static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + if (__b == __e) + return; + basic_string<_ECharT> __tmp(__b, __e); +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __tmp.data(), + __tmp.data() + __tmp.length()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); +#endif + } + + template + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + const _ECharT __sentinel = _ECharT{}; + if (*__b == __sentinel) + return; + basic_string<_ECharT> __tmp; + for (; *__b != __sentinel; ++__b) + __tmp.push_back(*__b); +#if defined(_LIBCPP_WIN32API) + string __utf8; + _Narrower()(back_inserter(__utf8), __tmp.data(), + __tmp.data() + __tmp.length()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); +#else + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); +#endif + } + + template + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; +#endif // !_LIBCPP_HAS_NO_LOCALIZATION + +template <> +struct _PathCVT<__path_value> { + + template + static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + for (; __b != __e; ++__b) + __dest.push_back(*__b); + } + + template + static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + __dest.append(__b, __e); + } + + template + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + const char __sentinel = char{}; + for (; *__b != __sentinel; ++__b) + __dest.push_back(*__b); + } + + template + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +#if defined(_LIBCPP_WIN32API) +template <> +struct _PathCVT { + + static void + __append_string(__path_string& __dest, const basic_string &__str) { + size_t __size = __char_to_wide(__str, nullptr, 0); + size_t __pos = __dest.size(); + __dest.resize(__pos + __size); + __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size); + } + + template + static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + basic_string __tmp(__b, __e); + __append_string(__dest, __tmp); + } + + template + static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + __append_range(__path_string& __dest, _Iter __b, _Iter __e) { + basic_string __tmp(__b, __e); + __append_string(__dest, __tmp); + } + + template + static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) { + const char __sentinel = char{}; + basic_string __tmp; + for (; *__b != __sentinel; ++__b) + __tmp.push_back(*__b); + __append_string(__dest, __tmp); + } + + template + static void __append_source(__path_string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +template +struct _PathExport { + typedef __narrow_to_utf8 _Narrower; + typedef __widen_from_utf8 _Widener; + + template + static void __append(_Str& __dest, const __path_string& __src) { + string __utf8; + _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size()); + _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size()); + } +}; + +template <> +struct _PathExport { + template + static void __append(_Str& __dest, const __path_string& __src) { + size_t __size = __wide_to_char(__src, nullptr, 0); + size_t __pos = __dest.size(); + __dest.resize(__size); + __wide_to_char(__src, const_cast(__dest.data()) + __pos, __size); + } +}; + +template <> +struct _PathExport { + template + static void __append(_Str& __dest, const __path_string& __src) { + __dest.append(__src.begin(), __src.end()); + } +}; + +template <> +struct _PathExport { + template + static void __append(_Str& __dest, const __path_string& __src) { + __dest.append(__src.begin(), __src.end()); + } +}; + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +struct _PathExport { + typedef __narrow_to_utf8 _Narrower; + + template + static void __append(_Str& __dest, const __path_string& __src) { + _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size()); + } +}; +#endif /* !_LIBCPP_HAS_NO_CHAR8_T */ +#endif /* _LIBCPP_WIN32API */ + +class _LIBCPP_TYPE_VIS path { + template + using _EnableIfPathable = + typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; + + template + using _SourceChar = typename __is_pathable<_Tp>::__char_type; + + template + using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; + +public: +#if defined(_LIBCPP_WIN32API) + typedef wchar_t value_type; + static constexpr value_type preferred_separator = L'\\'; +#else + typedef char value_type; + static constexpr value_type preferred_separator = '/'; +#endif + typedef basic_string string_type; + typedef basic_string_view __string_view; + + enum _LIBCPP_ENUM_VIS format : unsigned char { + auto_format, + native_format, + generic_format + }; + + // constructors and destructor + _LIBCPP_INLINE_VISIBILITY path() noexcept {} + _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {} + _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept + : __pn_(_VSTD::move(__p.__pn_)) {} + + _LIBCPP_INLINE_VISIBILITY + path(string_type&& __s, format = format::auto_format) noexcept + : __pn_(_VSTD::move(__s)) {} + + template > + path(const _Source& __src, format = format::auto_format) { + _SourceCVT<_Source>::__append_source(__pn_, __src); + } + + template + path(_InputIt __first, _InputIt __last, format = format::auto_format) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + } + +/* +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + // TODO Implement locale conversions. + template > + path(const _Source& __src, const locale& __loc, format = format::auto_format); + template + path(_InputIt __first, _InputIt _last, const locale& __loc, + format = format::auto_format); +#endif +*/ + + _LIBCPP_INLINE_VISIBILITY + ~path() = default; + + // assignments + _LIBCPP_INLINE_VISIBILITY + path& operator=(const path& __p) { + __pn_ = __p.__pn_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator=(path&& __p) noexcept { + __pn_ = _VSTD::move(__p.__pn_); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator=(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& assign(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator=(const _Source& __src) { + return this->assign(__src); + } + + template + _EnableIfPathable<_Source> assign(const _Source& __src) { + __pn_.clear(); + _SourceCVT<_Source>::__append_source(__pn_, __src); + return *this; + } + + template + path& assign(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + __pn_.clear(); + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + +public: + // appends +#if defined(_LIBCPP_WIN32API) + path& operator/=(const path& __p) { + auto __p_root_name = __p.__root_name(); + auto __p_root_name_size = __p_root_name.size(); + if (__p.is_absolute() || + (!__p_root_name.empty() && __p_root_name != __string_view(root_name().__pn_))) { + __pn_ = __p.__pn_; + return *this; + } + if (__p.has_root_directory()) { + path __root_name_str = root_name(); + __pn_ = __root_name_str.native(); + __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); + return *this; + } + if (has_filename() || (!has_root_directory() && is_absolute())) + __pn_ += preferred_separator; + __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); + return *this; + } + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator/=(const _Source& __src) { + return operator/=(path(__src)); + } + + template + _EnableIfPathable<_Source> append(const _Source& __src) { + return operator/=(path(__src)); + } + + template + path& append(_InputIt __first, _InputIt __last) { + return operator/=(path(__first, __last)); + } +#else + path& operator/=(const path& __p) { + if (__p.is_absolute()) { + __pn_ = __p.__pn_; + return *this; + } + if (has_filename()) + __pn_ += preferred_separator; + __pn_ += __p.native(); + return *this; + } + + // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src + // is known at compile time to be "/' since the user almost certainly intended + // to append a separator instead of overwriting the path with "/" + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator/=(const _Source& __src) { + return this->append(__src); + } + + template + _EnableIfPathable<_Source> append(const _Source& __src) { + using _Traits = __is_pathable<_Source>; + using _CVT = _PathCVT<_SourceChar<_Source> >; + bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src)); + if (__source_is_absolute) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_source(__pn_, __src); + return *this; + } + + template + path& append(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); + using _CVT = _PathCVT<_ItVal>; + if (__first != __last && __is_separator(*__first)) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_range(__pn_, __first, __last); + return *this; + } +#endif + + // concatenation + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const path& __x) { + __pn_ += __x.__pn_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const string_type& __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(__string_view __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const value_type* __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(value_type __x) { + __pn_ += __x; + return *this; + } + + template + typename enable_if<__can_convert_char<_ECharT>::value, path&>::type + operator+=(_ECharT __x) { + _PathCVT<_ECharT>::__append_source(__pn_, + basic_string_view<_ECharT>(&__x, 1)); + return *this; + } + + template + _EnableIfPathable<_Source> operator+=(const _Source& __x) { + return this->concat(__x); + } + + template + _EnableIfPathable<_Source> concat(const _Source& __x) { + _SourceCVT<_Source>::__append_source(__pn_, __x); + return *this; + } + + template + path& concat(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + + // modifiers + _LIBCPP_INLINE_VISIBILITY + void clear() noexcept { __pn_.clear(); } + + path& make_preferred() { +#if defined(_LIBCPP_WIN32API) + _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\'); +#endif + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& remove_filename() { + auto __fname = __filename(); + if (!__fname.empty()) + __pn_.erase(__fname.data() - __pn_.data()); + return *this; + } + + path& replace_filename(const path& __replacement) { + remove_filename(); + return (*this /= __replacement); + } + + path& replace_extension(const path& __replacement = path()); + + _LIBCPP_INLINE_VISIBILITY + void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } + + // private helper to allow reserving memory in the path + _LIBCPP_INLINE_VISIBILITY + void __reserve(size_t __s) { __pn_.reserve(__s); } + + // native format observers + _LIBCPP_INLINE_VISIBILITY + const string_type& native() const noexcept { return __pn_; } + + _LIBCPP_INLINE_VISIBILITY + const value_type* c_str() const noexcept { return __pn_.c_str(); } + + _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; } + +#if defined(_LIBCPP_WIN32API) + _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; } + + _VSTD::wstring generic_wstring() const { + _VSTD::wstring __s; + __s.resize(__pn_.size()); + _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/'); + return __s; + } + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const { + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s(__a); + __s.reserve(__pn_.size()); + _PathExport<_ECharT>::__append(__s, __pn_); + return __s; + } + + _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { + return string(); + } + _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const { + using _CVT = __narrow_to_utf8; + __u8_string __s; + __s.reserve(__pn_.size()); + _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + return __s; + } + + _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const { + return string(); + } + _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const { + return string(); + } + + // generic format observers + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const { + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s = string<_ECharT, _Traits, _Allocator>(__a); + // Note: This (and generic_u8string below) is slightly suboptimal as + // it iterates twice over the string; once to convert it to the right + // character type, and once to replace path delimiters. + _VSTD::replace(__s.begin(), __s.end(), + static_cast<_ECharT>('\\'), static_cast<_ECharT>('/')); + return __s; + } + + _VSTD::string generic_string() const { return generic_string(); } + _VSTD::u16string generic_u16string() const { return generic_string(); } + _VSTD::u32string generic_u32string() const { return generic_string(); } + __u8_string generic_u8string() const { + __u8_string __s = u8string(); + _VSTD::replace(__s.begin(), __s.end(), '\\', '/'); + return __s; + } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ +#else /* _LIBCPP_WIN32API */ + + _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; } +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } +#else + _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; } +#endif + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const { + using _CVT = __widen_from_utf8; + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s(__a); + __s.reserve(__pn_.size()); + _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + return __s; + } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { + return string(); + } +#endif + _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const { + return string(); + } + _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const { + return string(); + } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ + + // generic format observers + _VSTD::string generic_string() const { return __pn_; } +#ifndef _LIBCPP_HAS_NO_CHAR8_T + _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } +#else + _VSTD::string generic_u8string() const { return __pn_; } +#endif + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const { + return string<_ECharT, _Traits, _Allocator>(__a); + } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _VSTD::wstring generic_wstring() const { return string(); } +#endif + _VSTD::u16string generic_u16string() const { return string(); } + _VSTD::u32string generic_u32string() const { return string(); } +#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ +#endif /* !_LIBCPP_WIN32API */ + +private: + int __compare(__string_view) const; + __string_view __root_name() const; + __string_view __root_directory() const; + __string_view __root_path_raw() const; + __string_view __relative_path() const; + __string_view __parent_path() const; + __string_view __filename() const; + __string_view __stem() const; + __string_view __extension() const; + +public: + // compare + _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept { + return __compare(__p.__pn_); + } + _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { + return __compare(__s); + } + _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { + return __compare(__s); + } + _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { + return __compare(__s); + } + + // decomposition + _LIBCPP_INLINE_VISIBILITY path root_name() const { + return string_type(__root_name()); + } + _LIBCPP_INLINE_VISIBILITY path root_directory() const { + return string_type(__root_directory()); + } + _LIBCPP_INLINE_VISIBILITY path root_path() const { +#if defined(_LIBCPP_WIN32API) + return string_type(__root_path_raw()); +#else + return root_name().append(string_type(__root_directory())); +#endif + } + _LIBCPP_INLINE_VISIBILITY path relative_path() const { + return string_type(__relative_path()); + } + _LIBCPP_INLINE_VISIBILITY path parent_path() const { + return string_type(__parent_path()); + } + _LIBCPP_INLINE_VISIBILITY path filename() const { + return string_type(__filename()); + } + _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); } + _LIBCPP_INLINE_VISIBILITY path extension() const { + return string_type(__extension()); + } + + // query + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool + empty() const noexcept { + return __pn_.empty(); + } + + _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { + return !__root_name().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const { + return !__root_directory().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_root_path() const { + return !__root_path_raw().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const { + return !__relative_path().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const { + return !__parent_path().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_filename() const { + return !__filename().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); } + _LIBCPP_INLINE_VISIBILITY bool has_extension() const { + return !__extension().empty(); + } + + _LIBCPP_INLINE_VISIBILITY bool is_absolute() const { +#if defined(_LIBCPP_WIN32API) + __string_view __root_name_str = __root_name(); + __string_view __root_dir = __root_directory(); + if (__root_name_str.size() == 2 && __root_name_str[1] == ':') { + // A drive letter with no root directory is relative, e.g. x:example. + return !__root_dir.empty(); + } + // If no root name, it's relative, e.g. \example is relative to the current drive + if (__root_name_str.empty()) + return false; + if (__root_name_str.size() < 3) + return false; + // A server root name, like \\server, is always absolute + if (__root_name_str[0] != '/' && __root_name_str[0] != '\\') + return false; + if (__root_name_str[1] != '/' && __root_name_str[1] != '\\') + return false; + // Seems to be a server root name + return true; +#else + return has_root_directory(); +#endif + } + _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); } + + // relative paths + path lexically_normal() const; + path lexically_relative(const path& __base) const; + + _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const { + path __result = this->lexically_relative(__base); + if (__result.native().empty()) + return *this; + return __result; + } + + // iterators + class _LIBCPP_TYPE_VIS iterator; + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) + template + _LIBCPP_INLINE_VISIBILITY friend + typename enable_if::value && + is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << _VSTD::__quoted(__p.native()); + return __os; + } + + template + _LIBCPP_INLINE_VISIBILITY friend + typename enable_if::value || + !is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << _VSTD::__quoted(__p.string<_CharT, _Traits>()); + return __os; + } + + template + _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) { + basic_string<_CharT, _Traits> __tmp; + __is >> __quoted(__tmp); + __p = __tmp; + return __is; + } +#endif // !_LIBCPP_HAS_NO_LOCALIZATION + + friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) == 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) != 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) < 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) <= 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) > 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) >= 0; + } + + friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs, + const path& __rhs) { + path __result(__lhs); + __result /= __rhs; + return __result; + } +private: + inline _LIBCPP_INLINE_VISIBILITY path& + __assign_view(__string_view const& __s) noexcept { + __pn_ = string_type(__s); + return *this; + } + string_type __pn_; +}; + +inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept { + __lhs.swap(__rhs); +} + +_LIBCPP_FUNC_VIS +size_t hash_value(const path& __p) noexcept; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#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 new file mode 100644 index 0000000000..08039e4c8a --- /dev/null +++ b/lib/libcxx/include/__filesystem/path_iterator.h @@ -0,0 +1,130 @@ +// -*- 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___FILESYSTEM_PATH_ITERATOR_H +#define _LIBCPP___FILESYSTEM_PATH_ITERATOR_H + +#include <__availability> +#include <__config> +#include <__debug> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include +#include +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class _LIBCPP_TYPE_VIS path::iterator { +public: + enum _ParserState : unsigned char { + _Singular, + _BeforeBegin, + _InRootName, + _InRootDir, + _InFilenames, + _InTrailingSep, + _AtEnd + }; + +public: + typedef input_iterator_tag iterator_category; + typedef bidirectional_iterator_tag iterator_concept; + + typedef path value_type; + typedef ptrdiff_t difference_type; + typedef const path* pointer; + typedef path reference; + +public: + _LIBCPP_INLINE_VISIBILITY + iterator() + : __stashed_elem_(), __path_ptr_(nullptr), __entry_(), + __state_(_Singular) {} + + iterator(const iterator&) = default; + ~iterator() = default; + + iterator& operator=(const iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { return __stashed_elem_; } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { return &__stashed_elem_; } + + _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"); + return __increment(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator++(int) { + iterator __it(*this); + this->operator++(); + return __it; + } + + _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"); + return __decrement(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator--(int) { + iterator __it(*this); + this->operator--(); + return __it; + } + +private: + friend class path; + + inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&, + const iterator&); + + iterator& __increment(); + iterator& __decrement(); + + path __stashed_elem_; + const path* __path_ptr_; + path::__string_view __entry_; + _ParserState __state_; +}; + +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(); +} + +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 + +#endif // _LIBCPP___FILESYSTEM_PATH_ITERATOR_H diff --git a/lib/libcxx/include/__filesystem/perm_options.h b/lib/libcxx/include/__filesystem/perm_options.h new file mode 100644 index 0000000000..62cd8f5756 --- /dev/null +++ b/lib/libcxx/include/__filesystem/perm_options.h @@ -0,0 +1,73 @@ +// -*- 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___FILESYSTEM_PERM_OPTIONS_H +#define _LIBCPP___FILESYSTEM_PERM_OPTIONS_H + +#include <__availability> +#include <__config> + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { + replace = 1, + add = 2, + remove = 4, + nofollow = 8 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator~(perm_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +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 + +#endif // _LIBCPP___FILESYSTEM_PERM_OPTIONS_H diff --git a/lib/libcxx/include/__filesystem/perms.h b/lib/libcxx/include/__filesystem/perms.h new file mode 100644 index 0000000000..832f8b07e5 --- /dev/null +++ b/lib/libcxx/include/__filesystem/perms.h @@ -0,0 +1,91 @@ +// -*- 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___FILESYSTEM_PERMS_H +#define _LIBCPP___FILESYSTEM_PERMS_H + +#include <__availability> +#include <__config> + +#ifndef _LIBCPP_CXX03_LANG + +_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 +// others, the readonly flag is cleared. +enum class _LIBCPP_ENUM_VIS perms : unsigned { + none = 0, + + owner_read = 0400, + owner_write = 0200, + owner_exec = 0100, + owner_all = 0700, + + group_read = 040, + group_write = 020, + group_exec = 010, + group_all = 070, + + others_read = 04, + others_write = 02, + others_exec = 01, + others_all = 07, + + all = 0777, + + set_uid = 04000, + set_gid = 02000, + sticky_bit = 01000, + mask = 07777, + unknown = 0xFFFF, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator&(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator|(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator^(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator~(perms _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; } + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; } + +_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 + +#endif // _LIBCPP___FILESYSTEM_PERMS_H diff --git a/lib/libcxx/include/__filesystem/recursive_directory_iterator.h b/lib/libcxx/include/__filesystem/recursive_directory_iterator.h new file mode 100644 index 0000000000..b80d59750e --- /dev/null +++ b/lib/libcxx/include/__filesystem/recursive_directory_iterator.h @@ -0,0 +1,181 @@ +// -*- 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___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H +#define _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H + +#include <__availability> +#include <__config> +#include <__filesystem/directory_entry.h> +#include <__filesystem/directory_options.h> +#include <__filesystem/path.h> +#include <__iterator/iterator_traits.h> +#include <__memory/shared_ptr.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/enable_view.h> +#include +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +class recursive_directory_iterator { +public: + using value_type = directory_entry; + using difference_type = ptrdiff_t; + using pointer = directory_entry const*; + using reference = directory_entry const&; + using iterator_category = input_iterator_tag; + +public: + // constructors and destructor + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator() noexcept : __rec_(false) {} + + _LIBCPP_INLINE_VISIBILITY + explicit recursive_directory_iterator( + const path& __p, directory_options __xoptions = directory_options::none) + : recursive_directory_iterator(__p, __xoptions, nullptr) {} + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator(const path& __p, directory_options __xoptions, + error_code& __ec) + : recursive_directory_iterator(__p, __xoptions, &__ec) {} + + _LIBCPP_INLINE_VISIBILITY + 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; + + recursive_directory_iterator& + operator=(const recursive_directory_iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& + operator=(recursive_directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + __rec_ = __o.__rec_; + } + return *this; + } + + ~recursive_directory_iterator() = default; + + _LIBCPP_INLINE_VISIBILITY + const directory_entry& operator*() const { return __dereference(); } + + _LIBCPP_INLINE_VISIBILITY + const directory_entry* operator->() const { return &__dereference(); } + + recursive_directory_iterator& operator++() { return __increment(); } + + _LIBCPP_INLINE_VISIBILITY + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& increment(error_code& __ec) { + return __increment(&__ec); + } + + _LIBCPP_FUNC_VIS directory_options options() const; + _LIBCPP_FUNC_VIS int depth() const; + + _LIBCPP_INLINE_VISIBILITY + void pop() { __pop(); } + + _LIBCPP_INLINE_VISIBILITY + void pop(error_code& __ec) { __pop(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + bool recursion_pending() const { return __rec_; } + + _LIBCPP_INLINE_VISIBILITY + void disable_recursion_pending() { __rec_ = false; } + +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); + + inline _LIBCPP_INLINE_VISIBILITY friend bool + operator==(const recursive_directory_iterator&, + const recursive_directory_iterator&) noexcept; + + struct _LIBCPP_HIDDEN __shared_imp; + shared_ptr<__shared_imp> __imp_; + bool __rec_; +}; // class recursive_directory_iterator + +inline _LIBCPP_INLINE_VISIBILITY bool +operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +_LIBCPP_INLINE_VISIBILITY +inline bool operator!=(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} +// enable recursive_directory_iterator range-based for statements +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +begin(recursive_directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +end(recursive_directory_iterator) noexcept { + return recursive_directory_iterator(); +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true; + +template <> +_LIBCPP_AVAILABILITY_FILESYSTEM +inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif // _LIBCPP_CXX03_LANG + +#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 new file mode 100644 index 0000000000..098f085678 --- /dev/null +++ b/lib/libcxx/include/__filesystem/space_info.h @@ -0,0 +1,35 @@ +// -*- 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___FILESYSTEM_SPACE_INFO_H +#define _LIBCPP___FILESYSTEM_SPACE_INFO_H + +#include <__availability> +#include <__config> +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +struct _LIBCPP_TYPE_VIS space_info { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; +}; + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_SPACE_INFO_H diff --git a/lib/libcxx/include/__filesystem/u8path.h b/lib/libcxx/include/__filesystem/u8path.h new file mode 100644 index 0000000000..dca3b0c502 --- /dev/null +++ b/lib/libcxx/include/__filesystem/u8path.h @@ -0,0 +1,96 @@ +// -*- 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___FILESYSTEM_U8PATH_H +#define _LIBCPP___FILESYSTEM_U8PATH_H + +#include <__availability> +#include <__config> +#include <__filesystem/path.h> +#include + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_InputIt>::value, path>::type + u8path(_InputIt __f, _InputIt __l) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" + " or 'char8_t'"); +#if defined(_LIBCPP_WIN32API) + string __tmp(__f, __l); + using _CVT = __widen_from_utf8; + _VSTD::wstring __w; + __w.reserve(__tmp.size()); + _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size()); + return path(__w); +#else + return path(__f, __l); +#endif /* !_LIBCPP_WIN32API */ +} + +#if defined(_LIBCPP_WIN32API) +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_InputIt>::value, path>::type + u8path(_InputIt __f, _NullSentinel) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" + " or 'char8_t'"); + string __tmp; + const char __sentinel = char{}; + for (; *__f != __sentinel; ++__f) + __tmp.push_back(*__f); + using _CVT = __widen_from_utf8; + _VSTD::wstring __w; + __w.reserve(__tmp.size()); + _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size()); + return path(__w); +} +#endif /* _LIBCPP_WIN32API */ + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T + typename enable_if<__is_pathable<_Source>::value, path>::type + u8path(const _Source& __s) { + static_assert( +#ifndef _LIBCPP_HAS_NO_CHAR8_T + is_same::__char_type, char8_t>::value || +#endif + is_same::__char_type, char>::value, + "u8path(Source const&) requires Source have a character type of type " + "'char' or 'char8_t'"); +#if defined(_LIBCPP_WIN32API) + using _Traits = __is_pathable<_Source>; + return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s))); +#else + return path(__s); +#endif +} + +_LIBCPP_AVAILABILITY_FILESYSTEM_POP + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___FILESYSTEM_U8PATH_H diff --git a/lib/libcxx/include/__format/format_arg.h b/lib/libcxx/include/__format/format_arg.h new file mode 100644 index 0000000000..e76b0dd50d --- /dev/null +++ b/lib/libcxx/include/__format/format_arg.h @@ -0,0 +1,292 @@ +// -*- 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_FORMAT_ARG_H +#define _LIBCPP___FORMAT_FORMAT_ARG_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_parse_context.h> +#include <__functional_base> +#include <__memory/addressof.h> +#include <__variant/monostate.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format { +/// The type stored in @ref basic_format_arg. +/// +/// @note The 128-bit types are unconditionally in the list to avoid the values +/// of the enums to depend on the availability of 128-bit integers. +enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { + __none, + __boolean, + __char_type, + __int, + __long_long, + __i128, + __unsigned, + __unsigned_long_long, + __u128, + __float, + __double, + __long_double, + __const_char_type_ptr, + __string_view, + __ptr, + __handle +}; +} // namespace __format + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { + switch (__arg.__type_) { + case __format::__arg_t::__none: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), monostate{}); + case __format::__arg_t::__boolean: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__boolean); + case __format::__arg_t::__char_type: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__char_type); + case __format::__arg_t::__int: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__int); + case __format::__arg_t::__long_long: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_long); + case __format::__arg_t::__i128: +#ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__i128); +#else + _LIBCPP_UNREACHABLE(); +#endif + case __format::__arg_t::__unsigned: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__unsigned); + case __format::__arg_t::__unsigned_long_long: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), + __arg.__unsigned_long_long); + case __format::__arg_t::__u128: +#ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__u128); +#else + _LIBCPP_UNREACHABLE(); +#endif + case __format::__arg_t::__float: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__float); + case __format::__arg_t::__double: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__double); + case __format::__arg_t::__long_double: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_double); + case __format::__arg_t::__const_char_type_ptr: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), + __arg.__const_char_type_ptr); + case __format::__arg_t::__string_view: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__string_view); + case __format::__arg_t::__ptr: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__ptr); + case __format::__arg_t::__handle: + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__handle); + } + _LIBCPP_UNREACHABLE(); +} + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { +public: + class _LIBCPP_TEMPLATE_VIS handle; + + _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept + : __type_{__format::__arg_t::__none} {} + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { + return __type_ != __format::__arg_t::__none; + } + +private: + using char_type = typename _Context::char_type; + + // TODO FMT Implement constrain [format.arg]/4 + // Constraints: The template specialization + // typename Context::template formatter_type + // meets the Formatter requirements ([formatter.requirements]). The extent + // to which an implementation determines that the specialization meets the + // Formatter requirements is unspecified, except that as a minimum the + // expression + // typename Context::template formatter_type() + // .format(declval(), declval()) + // shall be well-formed when treated as an unevaluated operand. + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend __format_arg_store<_Ctx, _Args...> + make_format_args(const _Args&...); + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend decltype(auto) + visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg); + + union { + bool __boolean; + char_type __char_type; + int __int; + unsigned __unsigned; + long long __long_long; + unsigned long long __unsigned_long_long; +#ifndef _LIBCPP_HAS_NO_INT128 + __int128_t __i128; + __uint128_t __u128; +#endif + float __float; + double __double; + long double __long_double; + const char_type* __const_char_type_ptr; + basic_string_view __string_view; + const void* __ptr; + handle __handle; + }; + __format::__arg_t __type_; + + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(bool __v) noexcept + : __boolean(__v), __type_(__format::__arg_t::__boolean) {} + + template + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept + requires(same_as<_Tp, char_type> || + (same_as<_Tp, char> && same_as)) + : __char_type(__v), __type_(__format::__arg_t::__char_type) {} + + template <__libcpp_signed_integer _Tp> + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept { + if constexpr (sizeof(_Tp) <= sizeof(int)) { + __int = static_cast(__v); + __type_ = __format::__arg_t::__int; + } else if constexpr (sizeof(_Tp) <= sizeof(long long)) { + __long_long = static_cast(__v); + __type_ = __format::__arg_t::__long_long; + } +#ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) { + __i128 = __v; + __type_ = __format::__arg_t::__i128; + } +#endif + else + static_assert(sizeof(_Tp) == 0, "An unsupported signed integer was used"); + } + + template <__libcpp_unsigned_integer _Tp> + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept { + if constexpr (sizeof(_Tp) <= sizeof(unsigned)) { + __unsigned = static_cast(__v); + __type_ = __format::__arg_t::__unsigned; + } else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) { + __unsigned_long_long = static_cast(__v); + __type_ = __format::__arg_t::__unsigned_long_long; + } +#ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) { + __u128 = __v; + __type_ = __format::__arg_t::__u128; + } +#endif + else + static_assert(sizeof(_Tp) == 0, + "An unsupported unsigned integer was used"); + } + + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(float __v) noexcept + : __float(__v), __type_(__format::__arg_t::__float) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(double __v) noexcept + : __double(__v), __type_(__format::__arg_t::__double) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(long double __v) noexcept + : __long_double(__v), __type_(__format::__arg_t::__long_double) {} + + // Note not a 'noexcept' function. + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const char_type* __s) + : __const_char_type_ptr(__s), + __type_(__format::__arg_t::__const_char_type_ptr) { + _LIBCPP_ASSERT(__s, "Used a nullptr argument to initialize a C-string"); + } + + template + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg( + basic_string_view __s) noexcept + : __string_view{__s.data(), __s.size()}, + __type_(__format::__arg_t::__string_view) {} + + template + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg( + const basic_string& __s) noexcept + : __string_view{__s.data(), __s.size()}, + __type_(__format::__arg_t::__string_view) {} + + _LIBCPP_HIDE_FROM_ABI + explicit basic_format_arg(nullptr_t) noexcept + : __ptr(nullptr), __type_(__format::__arg_t::__ptr) {} + + template + requires is_void_v<_Tp> _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp* __p) noexcept + : __ptr(__p), __type_(__format::__arg_t::__ptr) {} + + template + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept + : __handle(__v), __type_(__format::__arg_t::__handle) {} +}; + +template +class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { + friend class basic_format_arg<_Context>; + +public: + _LIBCPP_HIDE_FROM_ABI + void format(basic_format_parse_context& __parse_ctx, _Context& __ctx) const { + __format_(__parse_ctx, __ctx, __ptr_); + } + +private: + const void* __ptr_; + void (*__format_)(basic_format_parse_context&, _Context&, const void*); + + template + _LIBCPP_HIDE_FROM_ABI explicit handle(const _Tp& __v) noexcept + : __ptr_(_VSTD::addressof(__v)), + __format_([](basic_format_parse_context& __parse_ctx, _Context& __ctx, const void* __ptr) { + typename _Context::template formatter_type<_Tp> __f; + __parse_ctx.advance_to(__f.parse(__parse_ctx)); + __ctx.advance_to(__f.format(*static_cast(__ptr), __ctx)); + }) {} +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMAT_ARG_H diff --git a/lib/libcxx/include/__format/format_args.h b/lib/libcxx/include/__format/format_args.h new file mode 100644 index 0000000000..0a26b95d1b --- /dev/null +++ b/lib/libcxx/include/__format/format_args.h @@ -0,0 +1,71 @@ +// -*- 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_FORMAT_ARGS_H +#define _LIBCPP___FORMAT_FORMAT_ARGS_H + +#include <__availability> +#include <__config> +#include <__format/format_fwd.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args { +public: + // TODO FMT Implement [format.args]/5 + // [Note 1: Implementations are encouraged to optimize the representation of + // basic_format_args for small number of formatting arguments by storing + // indices of type alternatives separately from values and packing the + // former. - end note] + // Note: Change __format_arg_store to use a built-in array. + _LIBCPP_HIDE_FROM_ABI basic_format_args() noexcept = default; + + template + _LIBCPP_HIDE_FROM_ABI basic_format_args( + const __format_arg_store<_Context, _Args...>& __store) noexcept + : __size_(sizeof...(_Args)), __data_(__store.__args.data()) {} + + _LIBCPP_HIDE_FROM_ABI + basic_format_arg<_Context> get(size_t __id) const noexcept { + return __id < __size_ ? __data_[__id] : basic_format_arg<_Context>{}; + } + + _LIBCPP_HIDE_FROM_ABI size_t __size() const noexcept { return __size_; } + +private: + size_t __size_{0}; + const basic_format_arg<_Context>* __data_{nullptr}; +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMAT_ARGS_H diff --git a/lib/libcxx/include/__format/format_context.h b/lib/libcxx/include/__format/format_context.h new file mode 100644 index 0000000000..570bf7e90d --- /dev/null +++ b/lib/libcxx/include/__format/format_context.h @@ -0,0 +1,165 @@ +// -*- 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_FORMAT_CONTEXT_H +#define _LIBCPP___FORMAT_FORMAT_CONTEXT_H + +#include <__availability> +#include <__config> +#include <__format/format_args.h> +#include <__format/format_fwd.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#include +#include +#endif + +#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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +requires output_iterator<_OutIt, const _CharT&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +/** + * Helper to create a basic_format_context. + * + * This is needed since the constructor is private. + */ +template +_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> +__format_context_create( + _OutIt __out_it, + basic_format_args> __args, + optional<_VSTD::locale>&& __loc = nullopt) { + return _VSTD::basic_format_context(_VSTD::move(__out_it), __args, + _VSTD::move(__loc)); +} +#else +template +_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT> +__format_context_create( + _OutIt __out_it, + basic_format_args> __args) { + return _VSTD::basic_format_context(_VSTD::move(__out_it), __args); +} +#endif + +// TODO FMT Implement [format.context]/4 +// [Note 1: For a given type charT, implementations are encouraged to provide a +// single instantiation of basic_format_context for appending to +// basic_string, vector, or any other container with contiguous +// storage by wrapping those in temporary objects with a uniform interface +// (such as a span) and polymorphic reallocation. - end note] + +using format_context = basic_format_context, char>; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wformat_context = basic_format_context, wchar_t>; +#endif + +template +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 + basic_format_context { +public: + using iterator = _OutIt; + using char_type = _CharT; + template + using formatter_type = formatter<_Tp, _CharT>; + + basic_format_context(const basic_format_context&) = delete; + basic_format_context& operator=(const basic_format_context&) = delete; + + _LIBCPP_HIDE_FROM_ABI basic_format_arg + arg(size_t __id) const { + return __args_.get(__id); + } +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { + if (!__loc_) + __loc_ = _VSTD::locale{}; + return *__loc_; + } +#endif + _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; } + _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; } + +private: + iterator __out_it_; + basic_format_args __args_; +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + + // The Standard doesn't specify how the locale is stored. + // [format.context]/6 + // std::locale locale(); + // Returns: The locale passed to the formatting function if the latter + // takes one, and std::locale() otherwise. + // This is done by storing the locale of the constructor in this optional. If + // locale() is called and the optional has no value the value will be created. + // This allows the implementation to lazily create the locale. + // 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>, + optional<_VSTD::locale>&&); + + // Note: the Standard doesn't specify the required constructors. + _LIBCPP_HIDE_FROM_ABI + explicit basic_format_context(_OutIt __out_it, + basic_format_args __args, + optional<_VSTD::locale>&& __loc) + : __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>); + + _LIBCPP_HIDE_FROM_ABI + explicit basic_format_context(_OutIt __out_it, + basic_format_args __args) + : __out_it_(_VSTD::move(__out_it)), __args_(__args) {} +#endif +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H diff --git a/lib/libcxx/include/__format/format_error.h b/lib/libcxx/include/__format/format_error.h index f983d0ce4a..ac1d708030 100644 --- a/lib/libcxx/include/__format/format_error.h +++ b/lib/libcxx/include/__format/format_error.h @@ -21,9 +21,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 @@ -51,6 +48,4 @@ __throw_format_error(const char* __s) { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FORMAT_FORMAT_ERROR_H diff --git a/lib/libcxx/include/__format/format_fwd.h b/lib/libcxx/include/__format/format_fwd.h new file mode 100644 index 0000000000..7da30aec51 --- /dev/null +++ b/lib/libcxx/include/__format/format_fwd.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___FORMAT_FORMAT_FWD_H +#define _LIBCPP___FORMAT_FORMAT_FWD_H + +#include <__availability> +#include <__config> +#include <__iterator/concepts.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg; + +template +struct _LIBCPP_TEMPLATE_VIS __format_arg_store; + +template +_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Ctx, _Args...> +make_format_args(const _Args&...); + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMAT_FWD_H diff --git a/lib/libcxx/include/__format/format_parse_context.h b/lib/libcxx/include/__format/format_parse_context.h index db39c1b548..289cab9f0e 100644 --- a/lib/libcxx/include/__format/format_parse_context.h +++ b/lib/libcxx/include/__format/format_parse_context.h @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 @@ -29,8 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // If the compiler has no concepts support, the format header will be disabled. // Without concepts support enable_if needs to be used and that too much effort // to support compilers with partial C++20 support. -#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && \ - !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) template class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { @@ -100,14 +96,14 @@ private: }; using format_parse_context = basic_format_parse_context; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS using wformat_parse_context = basic_format_parse_context; +#endif -#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) #endif //_LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H diff --git a/lib/libcxx/include/__format/format_string.h b/lib/libcxx/include/__format/format_string.h new file mode 100644 index 0000000000..885e572fc0 --- /dev/null +++ b/lib/libcxx/include/__format/format_string.h @@ -0,0 +1,169 @@ +// -*- 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_FORMAT_STRING_H +#define _LIBCPP___FORMAT_FORMAT_STRING_H + +#include <__config> +#include <__debug> +#include <__format/format_error.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format { + +template +struct _LIBCPP_TEMPLATE_VIS __parse_number_result { + const _CharT* __ptr; + uint32_t __value; +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> +__parse_number(const _CharT* __begin, const _CharT* __end); + +/** + * The maximum value of a numeric argument. + * + * This is used for: + * * arg-id + * * width as value or arg-id. + * * precision as value or arg-id. + * + * The value is compatible with the maximum formatting width and precision + * using the `%*` syntax on a 32-bit system. + */ +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) { + __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) { + size_t __value = __parse_ctx.next_arg_id(); + _LIBCPP_ASSERT(__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 = __parse_number(__begin, __end); + __parse_ctx.check_arg_id(__r.__value); + return __r; +} + +} // namespace __detail + +/** + * Parses a number. + * + * 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) { + static_assert(__format::__number_max == INT32_MAX, + "The algorithm is implemented based on this value."); + /* + * Limit the input to 9 digits, otherwise we need two checks during every + * iteration: + * - Are we at the end of the 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; + uint32_t __value = *__begin - _CharT('0'); + while (++__begin != __end) { + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + return {__begin, __value}; + + __value = __value * 10 + *__begin - _CharT('0'); + } + + if (__begin != __end_input && *__begin >= _CharT('0') && + *__begin <= _CharT('9')) { + + /* + * There are more than 9 digits, do additional validations: + * - Does the 10th digit exceed the maximum allowed value? + * - Are there more than 10 digits? + * (More than 10 digits always overflows the maximum.) + */ + uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0'); + if (__v > __number_max || + (__begin != __end_input && *__begin >= _CharT('0') && + *__begin <= _CharT('9'))) + __throw_format_error("The numeric value of the format-spec is too large"); + + __value = __v; + } + + return {__begin, __value}; +} + +/** + * Multiplexer for all parse functions. + * + * 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) { + switch (*__begin) { + case _CharT('0'): + return __detail::__parse_zero(__begin, __end, __parse_ctx); + + case _CharT(':'): + // This case is conditionally valid. It's allowed in an arg-id in the + // replacement-field, but not in the std-format-spec. The caller can + // provide a better diagnostic, so accept it here unconditionally. + case _CharT('}'): + return __detail::__parse_automatic(__begin, __end, __parse_ctx); + } + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + __throw_format_error( + "The arg-id of the format-spec starts with an invalid character"); + + return __detail::__parse_manual(__begin, __end, __parse_ctx); +} + +} // namespace __format + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_STRING_H diff --git a/lib/libcxx/include/__format/format_to_n_result.h b/lib/libcxx/include/__format/format_to_n_result.h new file mode 100644 index 0000000000..b973dc5c1d --- /dev/null +++ b/lib/libcxx/include/__format/format_to_n_result.h @@ -0,0 +1,41 @@ +// -*- 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_FORMAT_TO_N_RESULT_H +#define _LIBCPP___FORMAT_FORMAT_TO_N_RESULT_H + +#include <__config> +#include <__iterator/incrementable_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +struct _LIBCPP_TEMPLATE_VIS format_to_n_result { + _OutIt out; + iter_difference_t<_OutIt> size; +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_TO_N_RESULT_H diff --git a/lib/libcxx/include/__format/formatter.h b/lib/libcxx/include/__format/formatter.h new file mode 100644 index 0000000000..38b73bba32 --- /dev/null +++ b/lib/libcxx/include/__format/formatter.h @@ -0,0 +1,290 @@ +// -*- 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_FORMATTER_H +#define _LIBCPP___FORMAT_FORMATTER_H + +#include <__algorithm/copy.h> +#include <__algorithm/fill_n.h> +#include <__availability> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_string.h> +#include <__format/parser_std_format_spec.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +/// The default formatter template. +/// +/// [format.formatter.spec]/5 +/// If F is a disabled specialization of formatter, these values are false: +/// - is_default_constructible_v, +/// - is_copy_constructible_v, +/// - is_move_constructible_v, +/// - is_copy_assignable, and +/// - is_move_assignable. +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { + formatter() = delete; + formatter(const formatter&) = delete; + formatter& operator=(const formatter&) = delete; +}; + +namespace __format_spec { + +_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, + _Flags::_Sign __sign) { + if (__negative) + *__buf++ = '-'; + else + switch (__sign) { + case _Flags::_Sign::__default: + case _Flags::_Sign::__minus: + // No sign added. + break; + case _Flags::_Sign::__plus: + *__buf++ = '+'; + break; + case _Flags::_Sign::__space: + *__buf++ = ' '; + break; + } + + return __buf; +} + +_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) { + switch (c) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + } + return c; +} + +} // namespace __format_spec + +namespace __formatter { + +/** The character types that formatters are specialized for. */ +template +concept __char_type = same_as<_CharT, char> || same_as<_CharT, wchar_t>; + +struct _LIBCPP_TEMPLATE_VIS __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::_Flags::_Alignment __align) { + _LIBCPP_ASSERT(__width > __size, + "Don't call this function when no padding is required"); + _LIBCPP_ASSERT( + __align != __format_spec::_Flags::_Alignment::__default, + "Caller should adjust the default to the value required by the type"); + + size_t __fill = __width - __size; + switch (__align) { + case __format_spec::_Flags::_Alignment::__default: + _LIBCPP_UNREACHABLE(); + + case __format_spec::_Flags::_Alignment::__left: + return {0, __fill}; + + case __format_spec::_Flags::_Alignment::__center: { + // The extra padding is divided per [format.string.std]/3 + // __before = floor(__fill, 2); + // __after = ceil(__fill, 2); + size_t __before = __fill / 2; + size_t __after = __fill - __before; + return {__before, __after}; + } + case __format_spec::_Flags::_Alignment::__right: + return {__fill, 0}; + } + _LIBCPP_UNREACHABLE(); +} + +/** + * Writes the input to the output with the required padding. + * + * Since the output column width is specified the function can be used for + * ASCII and Unicode input. + * + * @pre [@a __first, @a __last) is a valid range. + * @pre @a __size <= @a __width. Using this function when this pre-condition + * doesn't hold incurs an unwanted overhead. + * + * @param __out_it The output iterator to write to. + * @param __first Pointer to the first element to write. + * @param __last Pointer beyond the last element to write. + * @param __size The (estimated) output column width. When the elements + * to be written are ASCII the following condition holds + * @a __size == @a __last - @a __first. + * @param __width The number of output columns to write. + * @param __fill The character used for the alignment of the output. + * TODO FMT Will probably change to support Unicode grapheme + * cluster. + * @param __alignment The requested alignment. + * + * @returns An iterator pointing beyond the last element written. + * + * @note The type of the elements in range [@a __first, @a __last) can differ + * from the type of @a __fill. Integer output uses @c std::to_chars for its + * conversion, which means the [@a __first, @a __last) always contains elements + * of the type @c char. + */ +template +_LIBCPP_HIDE_FROM_ABI auto +__write(output_iterator auto __out_it, const _CharT* __first, + const _CharT* __last, size_t __size, size_t __width, _Fill __fill, + __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) { + + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT(__size < __width, "Precondition failure"); + + __padding_size_result __padding = + __padding_size(__size, __width, __alignment); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); + __out_it = _VSTD::copy(__first, __last, _VSTD::move(__out_it)); + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); +} + +/** + * @overload + * + * 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(output_iterator auto __out_it, const _CharT* __first, + const _CharT* __last, size_t __size, size_t __width, _Fill __fill, + __format_spec::_Flags::_Alignment __alignment, 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 = __padding_size(__size + __num_trailing_zeros, __width, __alignment); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); + __out_it = _VSTD::copy(__first, __exponent, _VSTD::move(__out_it)); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); + __out_it = _VSTD::copy(__exponent, __last, _VSTD::move(__out_it)); + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); +} + +/** + * @overload + * + * Uses a transformation operation before writing an element. + * + * TODO FMT Fill will probably change to support Unicode grapheme cluster. + */ +template +_LIBCPP_HIDE_FROM_ABI auto +__write(output_iterator auto __out_it, const _CharT* __first, + const _CharT* __last, size_t __size, _UnaryOperation __op, + size_t __width, _Fill __fill, + __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) { + + _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT(__size < __width, "Precondition failure"); + + __padding_size_result __padding = + __padding_size(__size, __width, __alignment); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); + __out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it), __op); + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); +} + +/** + * Writes Unicode input to the output with the required padding. + * + * This function does almost the same as the @ref __write function, but handles + * the width estimation of the Unicode input. + * + * @param __str The range [@a __first, @a __last). + * @param __precision The width to truncate the input string to, use @c -1 for + * no limit. + */ +template +_LIBCPP_HIDE_FROM_ABI auto +__write_unicode(output_iterator auto __out_it, + basic_string_view<_CharT> __str, ptrdiff_t __width, + ptrdiff_t __precision, _Fill __fill, + __format_spec::_Flags::_Alignment __alignment) + -> decltype(__out_it) { + + // This value changes when there Unicode column width limits the output + // size. + auto __last = __str.end(); + if (__width != 0 || __precision != -1) { + __format_spec::__string_alignment<_CharT> __format_traits = + __format_spec::__get_string_alignment(__str.begin(), __str.end(), + __width, __precision); + + if (__format_traits.__align) + return __write(_VSTD::move(__out_it), __str.begin(), + __format_traits.__last, __format_traits.__size, __width, + __fill, __alignment); + + // No alignment required update the output based on the precision. + // This might be the same as __str.end(). + __last = __format_traits.__last; + } + + // Copy the input to the output. The output size might be limited by the + // precision. + return _VSTD::copy(__str.begin(), __last, _VSTD::move(__out_it)); +} + +} // namespace __formatter + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_H diff --git a/lib/libcxx/include/__format/formatter_bool.h b/lib/libcxx/include/__format/formatter_bool.h new file mode 100644 index 0000000000..1e40bc0a43 --- /dev/null +++ b/lib/libcxx/include/__format/formatter_bool.h @@ -0,0 +1,147 @@ +// -*- 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_FORMATTER_BOOL_H +#define _LIBCPP___FORMAT_FORMATTER_BOOL_H + +#include <__availability> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +template +class _LIBCPP_TEMPLATE_VIS __parser_bool : public __parser_integral<_CharT> { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parser_integral<_CharT>::__parse(__parse_ctx); + + switch (this->__type) { + case _Flags::_Type::__default: + this->__type = _Flags::_Type::__string; + [[fallthrough]]; + case _Flags::_Type::__string: + this->__handle_bool(); + break; + + case _Flags::_Type::__char: + this->__handle_char(); + break; + + case _Flags::_Type::__binary_lower_case: + case _Flags::_Type::__binary_upper_case: + case _Flags::_Type::__octal: + case _Flags::_Type::__decimal: + case _Flags::_Type::__hexadecimal_lower_case: + case _Flags::_Type::__hexadecimal_upper_case: + this->__handle_integer(); + break; + + default: + __throw_format_error( + "The format-spec type has a type not supported for a bool argument"); + } + + return __it; + } +}; + +template +struct _LIBCPP_TEMPLATE_VIS __bool_strings; + +template <> +struct _LIBCPP_TEMPLATE_VIS __bool_strings { + static constexpr string_view __true{"true"}; + static constexpr string_view __false{"false"}; +}; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct _LIBCPP_TEMPLATE_VIS __bool_strings { + static constexpr wstring_view __true{L"true"}; + static constexpr wstring_view __false{L"false"}; +}; +#endif + +template +using __formatter_bool = __formatter_integral<__parser_bool<_CharT>>; + +} //namespace __format_spec + +// [format.formatter.spec]/2.3 +// For each charT, for each cv-unqualified arithmetic type ArithmeticT other +// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization + +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_bool<_CharT> { + using _Base = __format_spec::__formatter_bool<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) + -> decltype(__ctx.out()) { + if (this->__type != __format_spec::_Flags::_Type::__string) + return _Base::format(static_cast(__value), __ctx); + + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (this->__locale_specific_form) { + const auto& __np = use_facet>(__ctx.locale()); + basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename(); + return __formatter::__write_unicode( + __ctx.out(), basic_string_view<_CharT>{__str}, this->__width, -1, + this->__fill, this->__alignment); + } +#endif + basic_string_view<_CharT> __str = + __value ? __format_spec::__bool_strings<_CharT>::__true + : __format_spec::__bool_strings<_CharT>::__false; + + // The output only uses ASCII so every character is one column. + unsigned __size = __str.size(); + if (__size >= this->__width) + return _VSTD::copy(__str.begin(), __str.end(), __ctx.out()); + + return __formatter::__write(__ctx.out(), __str.begin(), __str.end(), __size, + this->__width, this->__fill, this->__alignment); + } +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_BOOL_H diff --git a/lib/libcxx/include/__format/formatter_char.h b/lib/libcxx/include/__format/formatter_char.h new file mode 100644 index 0000000000..2131de0778 --- /dev/null +++ b/lib/libcxx/include/__format/formatter_char.h @@ -0,0 +1,104 @@ +// -*- 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_FORMATTER_CHAR_H +#define _LIBCPP___FORMAT_FORMATTER_CHAR_H + +#include <__availability> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +template +class _LIBCPP_TEMPLATE_VIS __parser_char : public __parser_integral<_CharT> { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parser_integral<_CharT>::__parse(__parse_ctx); + + switch (this->__type) { + case _Flags::_Type::__default: + this->__type = _Flags::_Type::__char; + [[fallthrough]]; + case _Flags::_Type::__char: + this->__handle_char(); + break; + + case _Flags::_Type::__binary_lower_case: + case _Flags::_Type::__binary_upper_case: + case _Flags::_Type::__octal: + case _Flags::_Type::__decimal: + case _Flags::_Type::__hexadecimal_lower_case: + case _Flags::_Type::__hexadecimal_upper_case: + this->__handle_integer(); + break; + + default: + __throw_format_error( + "The format-spec type has a type not supported for a char argument"); + } + + return __it; + } +}; + +template +using __formatter_char = __formatter_integral<__parser_char<_CharT>>; + +} // namespace __format_spec + +// [format.formatter.spec]/2.1 The specializations + +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_char {}; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_char { + using _Base = __format_spec::__formatter_char; + + _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) + -> decltype(__ctx.out()) { + return _Base::format(static_cast(__value), __ctx); + } +}; + +template <> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_char {}; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_CHAR_H diff --git a/lib/libcxx/include/__format/formatter_floating_point.h b/lib/libcxx/include/__format/formatter_floating_point.h new file mode 100644 index 0000000000..2e710b409d --- /dev/null +++ b/lib/libcxx/include/__format/formatter_floating_point.h @@ -0,0 +1,717 @@ +// -*- 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_FORMATTER_FLOATING_POINT_H +#define _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H + +#include <__algorithm/copy.h> +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/find.h> +#include <__algorithm/min.h> +#include <__algorithm/rotate.h> +#include <__algorithm/transform.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__debug> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_string.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include <__utility/move.h> +#include +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +# if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +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"); + 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"); + 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"); + return __r.ptr; +} + +// https://en.cppreference.com/w/cpp/language/types#cite_note-1 +// float min subnormal: +/-0x1p-149 max: +/- 3.402,823,4 10^38 +// double min subnormal: +/-0x1p-1074 max +/- 1.797,693,134,862,315,7 10^308 +// long double (x86) min subnormal: +/-0x1p-16446 max: +/- 1.189,731,495,357,231,765,021 10^4932 +// +// The maximum number of digits required for the integral part is based on the +// maximum's value power of 10. Every power of 10 requires one additional +// decimal digit. +// The maximum number of digits required for the fractional part is based on +// the minimal subnormal hexadecimal output's power of 10. Every division of a +// fraction's binary 1 by 2, requires one additional decimal digit. +// +// The maximum size of a formatted value depends on the selected output format. +// Ignoring the fact the format string can request a precision larger than the +// values maximum required, these values are: +// +// sign 1 code unit +// __max_integral +// radix point 1 code unit +// __max_fractional +// exponent character 1 code unit +// sign 1 code unit +// __max_fractional_value +// ----------------------------------- +// total 4 code units extra required. +// +// TODO FMT Optimize the storage to avoid storing digits that are known to be zero. +// https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/ + +// TODO FMT Add long double specialization when to_chars has proper long double support. +template +struct __traits; + +template +static constexpr size_t __float_buffer_size(int __precision) { + using _Traits = __traits<_Fp>; + return 4 + _Traits::__max_integral + __precision + _Traits::__max_fractional_value; +} + +template <> +struct __traits { + static constexpr int __max_integral = 38; + static constexpr int __max_fractional = 149; + static constexpr int __max_fractional_value = 3; + static constexpr size_t __stack_buffer_size = 256; + + static constexpr int __hex_precision_digits = 3; +}; + +template <> +struct __traits { + static constexpr int __max_integral = 308; + static constexpr int __max_fractional = 1074; + static constexpr int __max_fractional_value = 4; + static constexpr size_t __stack_buffer_size = 1024; + + static constexpr int __hex_precision_digits = 4; +}; + +/// Helper class to store the conversion buffer. +/// +/// Depending on the maxium size required for a value, the buffer is allocated +/// on the stack or the heap. +template +class _LIBCPP_TEMPLATE_VIS __float_buffer { + using _Traits = __traits<_Fp>; + +public: + // TODO FMT Improve this constructor to do a better estimate. + // When using a scientific formatting with a precision of 6 a stack buffer + // will always suffice. At the moment that isn't important since floats and + // doubles use a stack buffer, unless the precision used in the format string + // is large. + // When supporting long doubles the __max_integral part becomes 4932 which + // may be too much for some platforms. For these cases a better estimate is + // required. + explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision) + : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) { + + // When the precision is larger than _Traits::__max_fractional the digits in + // the range (_Traits::__max_fractional, precision] will contain the value + // zero. There's no need to request to_chars to write these zeros: + // - When the value is large a temporary heap buffer needs to be allocated. + // - When to_chars writes the values they need to be "copied" to the output: + // - char: std::fill on the output iterator is faster than std::copy. + // - wchar_t: same argument as char, but additional std::copy won't work. + // The input is always a char buffer, so every char in the buffer needs + // to be converted from a char to a wchar_t. + if (__precision_ > _Traits::__max_fractional) { + __num_trailing_zeros_ = __precision_ - _Traits::__max_fractional; + __precision_ = _Traits::__max_fractional; + } + + __size_ = __format_spec::__float_buffer_size<_Fp>(__precision_); + if (__size_ > _Traits::__stack_buffer_size) + // The allocated buffer's contents don't need initialization. + __begin_ = allocator{}.allocate(__size_); + else + __begin_ = __buffer_; + } + + _LIBCPP_HIDE_FROM_ABI ~__float_buffer() { + if (__size_ > _Traits::__stack_buffer_size) + allocator{}.deallocate(__begin_, __size_); + } + _LIBCPP_HIDE_FROM_ABI __float_buffer(const __float_buffer&) = delete; + _LIBCPP_HIDE_FROM_ABI __float_buffer& operator=(const __float_buffer&) = delete; + + _LIBCPP_HIDE_FROM_ABI char* begin() const { return __begin_; } + _LIBCPP_HIDE_FROM_ABI char* end() const { return __begin_ + __size_; } + + _LIBCPP_HIDE_FROM_ABI int __precision() const { return __precision_; } + _LIBCPP_HIDE_FROM_ABI int __num_trailing_zeros() const { return __num_trailing_zeros_; } + _LIBCPP_HIDE_FROM_ABI void __remove_trailing_zeros() { __num_trailing_zeros_ = 0; } + +private: + int __precision_; + int __num_trailing_zeros_{0}; + size_t __size_; + char* __begin_; + char __buffer_[_Traits::__stack_buffer_size]; +}; + +struct __float_result { + /// Points at the beginning of the integral part in the buffer. + /// + /// When there's no sign character this points at the start of the buffer. + char* __integral; + + /// Points at the radix point, when not present it's the same as \ref __last. + char* __radix_point; + + /// Points at the exponent character, when not present it's the same as \ref __last. + char* __exponent; + + /// Points beyond the last written element in the buffer. + char* __last; +}; + +/// Finds the position of the exponent character 'e' at the end of the buffer. +/// +/// Assuming there is an exponent the input will terminate with +/// eSdd and eSdddd (S = sign, d = digit) +/// +/// \returns a pointer to the exponent or __last when not found. +constexpr inline _LIBCPP_HIDE_FROM_ABI char* __find_exponent(char* __first, char* __last) { + ptrdiff_t __size = __last - __first; + if (__size > 4) { + __first = __last - _VSTD::min(__size, ptrdiff_t(6)); + for (; __first != __last - 3; ++__first) { + if (*__first == 'e') + return __first; + } + } + return __last; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffer<_Fp>& __buffer, _Tp __value, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value); + + __result.__exponent = __format_spec::__find_exponent(__result.__integral, __result.__last); + + // Constrains: + // - There's at least one decimal digit before the radix point. + // - The radix point, when present, is placed before the exponent. + __result.__radix_point = _VSTD::find(__result.__integral + 1, __result.__exponent, '.'); + + // When the radix point isn't found its position is the exponent instead of + // __result.__last. + if (__result.__radix_point == __result.__exponent) + __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."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + if (__precision == -1) + __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex); + else + __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex, __precision); + + // H = one or more hex-digits + // S = sign + // D = one or more decimal-digits + // When the fractional part is zero and no precision the output is 0p+0 + // else the output is 0.HpSD + // So testing the second position can differentiate between these two cases. + char* __first = __integral + 1; + if (*__first == '.') { + __result.__radix_point = __first; + // One digit is the minimum + // 0.hpSd + // ^-- last + // ^---- integral = end of search + // ^-------- start of search + // 0123456 + // + // Four digits is the maximum + // 0.hpSdddd + // ^-- last + // ^---- integral = end of search + // ^-------- start of search + // 0123456789 + static_assert(__traits<_Fp>::__hex_precision_digits <= 4, "Guard against possible underflow."); + + char* __last = __result.__last - 2; + __first = __last - __traits<_Fp>::__hex_precision_digits; + __result.__exponent = _VSTD::find(__first, __last, 'p'); + } else { + __result.__radix_point = __result.__last; + __result.__exponent = __first; + } + + // 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."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_upper_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result = + __format_spec::__format_buffer_hexadecimal_lower_case(__buffer, __value, __precision, __integral); + _VSTD::transform(__result.__integral, __result.__exponent, __result.__integral, __hex_to_upper); + *__result.__exponent = 'P'; + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = + __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision); + + char* __first = __integral + 1; + _LIBCPP_ASSERT(__first != __result.__last, "No exponent present"); + if (*__first == '.') { + __result.__radix_point = __first; + __result.__exponent = __format_spec::__find_exponent(__first + 1, __result.__last); + } else { + __result.__radix_point = __result.__last; + __result.__exponent = __first; + } + + // 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."); + // clang-format on + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_upper_case(const __float_buffer<_Fp>& __buffer, + _Tp __value, int __precision, + char* __integral) { + __float_result __result = + __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __precision, __integral); + *__result.__exponent = 'E'; + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + __float_result __result; + __result.__integral = __integral; + __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::fixed, __precision); + + // When there's no precision there's no radix point. + // Else the radix point is placed at __precision + 1 from the end. + // By converting __precision to a bool the subtraction can be done + // unconditionally. + __result.__radix_point = __result.__last - (__precision + bool(__precision)); + __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."); + // clang-format on + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + + __buffer.__remove_trailing_zeros(); + + __float_result __result; + __result.__integral = __integral; + __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision); + + char* __first = __integral + 1; + if (__first == __result.__last) { + __result.__radix_point = __result.__last; + __result.__exponent = __result.__last; + } else { + __result.__exponent = __format_spec::__find_exponent(__first, __result.__last); + if (__result.__exponent != __result.__last) + // In scientific mode if there's a radix point it will always be after + // the first digit. (This is the position __first points at). + __result.__radix_point = *__first == '.' ? __first : __result.__last; + else { + // In fixed mode the algorithm truncates trailing spaces and possibly the + // radix point. There's no good guess for the position of the radix point + // therefore scan the output after the first digit. + __result.__radix_point = _VSTD::find(__first, __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."); + // clang-format on + + return __result; +} + +template +_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_upper_case(__float_buffer<_Fp>& __buffer, _Tp __value, + int __precision, char* __integral) { + __float_result __result = + __format_spec::__format_buffer_general_lower_case(__buffer, __value, __precision, __integral); + if (__result.__exponent != __result.__last) + *__result.__exponent = 'E'; + return __result; +} + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION +template +_LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(_OutIt __out_it, const __float_buffer<_Fp>& __buffer, + const __float_result& __result, _VSTD::locale __loc, + size_t __width, _Flags::_Alignment __alignment, + _CharT __fill) { + const auto& __np = use_facet>(__loc); + string __grouping = __np.grouping(); + char* __first = __result.__integral; + // When no radix point or exponent are present __last will be __result.__last. + char* __last = _VSTD::min(__result.__radix_point, __result.__exponent); + + ptrdiff_t __digits = __last - __first; + if (!__grouping.empty()) { + if (__digits <= __grouping[0]) + __grouping.clear(); + else + __grouping = __determine_grouping(__digits, __grouping); + } + + size_t __size = __result.__last - __buffer.begin() + // Formatted string + __buffer.__num_trailing_zeros() + // Not yet rendered zeros + __grouping.size() - // Grouping contains one + !__grouping.empty(); // additional character + + __formatter::__padding_size_result __padding = {0, 0}; + bool __zero_padding = __alignment == _Flags::_Alignment::__default; + if (__size < __width) { + if (__zero_padding) { + __alignment = _Flags::_Alignment::__right; + __fill = _CharT('0'); + } + + __padding = __formatter::__padding_size(__size, __width, __alignment); + } + + // sign and (zero padding or alignment) + if (__zero_padding && __first != __buffer.begin()) + *__out_it++ = *__buffer.begin(); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); + if (!__zero_padding && __first != __buffer.begin()) + *__out_it++ = *__buffer.begin(); + + // integral part + if (__grouping.empty()) { + __out_it = _VSTD::copy_n(__first, __digits, _VSTD::move(__out_it)); + } else { + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + _CharT __sep = __np.thousands_sep(); + // 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. + while (true) { + __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + } + + // fractional part + if (__result.__radix_point != __result.__last) { + *__out_it++ = __np.decimal_point(); + __out_it = _VSTD::copy(__result.__radix_point + 1, __result.__exponent, _VSTD::move(__out_it)); + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __buffer.__num_trailing_zeros(), _CharT('0')); + } + + // exponent + if (__result.__exponent != __result.__last) + __out_it = _VSTD::copy(__result.__exponent, __result.__last, _VSTD::move(__out_it)); + + // alignment + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); +} + +# endif // _LIBCPP_HAS_NO_LOCALIZATION + +template <__formatter::__char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatter_floating_point : public __parser_floating_point<_CharT> { +public: + template + _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) { + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + + bool __negative = _VSTD::signbit(__value); + + if (!_VSTD::isfinite(__value)) [[unlikely]] + return __format_non_finite(__ctx.out(), __negative, _VSTD::isnan(__value)); + + bool __has_precision = this->__has_precision_field(); + if (this->__precision_needs_substitution()) + this->__substitute_precision_arg_id(__ctx.arg(this->__precision)); + + // Depending on the std-format-spec string the sign and the value + // might not be outputted together: + // - zero-padding may insert additional '0' characters. + // Therefore the value is processed as a non negative value. + // The function @ref __insert_sign will insert a '-' when the value was + // negative. + + if (__negative) + __value = _VSTD::copysign(__value, +1.0); + + // TODO FMT _Fp should just be _Tp when to_chars has proper long double support. + using _Fp = conditional_t, double, _Tp>; + // Force the type of the precision to avoid -1 to become an unsigned value. + __float_buffer<_Fp> __buffer(__has_precision ? int(this->__precision) : -1); + __float_result __result = __format_buffer(__buffer, __value, __negative, __has_precision); + + if (this->__alternate_form && __result.__radix_point == __result.__last) { + *__result.__last++ = '.'; + + // When there is an exponent the point needs to be moved before the + // exponent. When there's no exponent the rotate does nothing. Since + // rotate tests whether the operation is a nop, call it unconditionally. + _VSTD::rotate(__result.__exponent, __result.__last - 1, __result.__last); + __result.__radix_point = __result.__exponent; + + // The radix point is always placed before the exponent. + // - No exponent needs to point to the new last. + // - An exponent needs to move one position to the right. + // So it's safe to increment the value unconditionally. + ++__result.__exponent; + } + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (this->__locale_specific_form) + return __format_spec::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(), + this->__width, this->__alignment, this->__fill); +# endif + + ptrdiff_t __size = __result.__last - __buffer.begin(); + int __num_trailing_zeros = __buffer.__num_trailing_zeros(); + if (__size + __num_trailing_zeros >= this->__width) { + if (__num_trailing_zeros && __result.__exponent != __result.__last) + // Insert trailing zeros before exponent character. + return _VSTD::copy(__result.__exponent, __result.__last, + _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__exponent, __ctx.out()), + __num_trailing_zeros, _CharT('0'))); + + return _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__last, __ctx.out()), __num_trailing_zeros, + _CharT('0')); + } + + auto __out_it = __ctx.out(); + char* __first = __buffer.begin(); + if (this->__alignment == _Flags::_Alignment::__default) { + // When there is a sign output it before the padding. Note the __size + // doesn't need any adjustment, regardless whether the sign is written + // here or in __formatter::__write. + if (__first != __result.__integral) + *__out_it++ = *__first++; + // After the sign is written, zero padding is the same a right alignment + // with '0'. + this->__alignment = _Flags::_Alignment::__right; + this->__fill = _CharT('0'); + } + + if (__num_trailing_zeros) + return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill, + this->__alignment, __result.__exponent, __num_trailing_zeros); + + return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill, + this->__alignment); + } + +private: + template + _LIBCPP_HIDE_FROM_ABI _OutIt __format_non_finite(_OutIt __out_it, bool __negative, bool __isnan) { + char __buffer[4]; + char* __last = __insert_sign(__buffer, __negative, this->__sign); + + // to_char can return inf, infinity, nan, and nan(n-char-sequence). + // The format library requires inf and nan. + // All in one expression to avoid dangling references. + __last = _VSTD::copy_n(&("infnanINFNAN"[6 * (this->__type == _Flags::_Type::__float_hexadecimal_upper_case || + this->__type == _Flags::_Type::__scientific_upper_case || + this->__type == _Flags::_Type::__fixed_upper_case || + this->__type == _Flags::_Type::__general_upper_case) + + 3 * __isnan]), + 3, __last); + + // [format.string.std]/13 + // A zero (0) character preceding the width field pads the field with + // leading zeros (following any indication of sign or base) to the field + // width, except when applied to an infinity or NaN. + if (this->__alignment == _Flags::_Alignment::__default) + this->__alignment = _Flags::_Alignment::__right; + + ptrdiff_t __size = __last - __buffer; + if (__size >= this->__width) + return _VSTD::copy_n(__buffer, __size, _VSTD::move(__out_it)); + + return __formatter::__write(_VSTD::move(__out_it), __buffer, __last, __size, this->__width, this->__fill, + this->__alignment); + } + + /// Fills the buffer with the data based on the requested formatting. + /// + /// This function, when needed, turns the characters to upper case and + /// determines the "interesting" locations which are returned to the caller. + /// + /// This means the caller never has to convert the contents of the buffer to + /// upper case or search for radix points and the location of the exponent. + /// This gives a bit of overhead. The original code didn't do that, but due + /// to the number of possible additional work needed to turn this number to + /// the proper output the code was littered with tests for upper cases and + /// searches for radix points and exponents. + /// - When a precision larger than the type's precision is selected + /// additional zero characters need to be written before the exponent. + /// - alternate form needs to add a radix point when not present. + /// - localization needs to do grouping in the integral part. + template + // TODO FMT _Fp should just be _Tp when to_chars has proper long double support. + _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer(__float_buffer<_Fp>& __buffer, _Tp __value, bool __negative, + bool __has_precision) { + char* __first = __insert_sign(__buffer.begin(), __negative, this->__sign); + switch (this->__type) { + case _Flags::_Type::__default: + return __format_spec::__format_buffer_default(__buffer, __value, __first); + + case _Flags::_Type::__float_hexadecimal_lower_case: + return __format_spec::__format_buffer_hexadecimal_lower_case( + __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first); + + case _Flags::_Type::__float_hexadecimal_upper_case: + return __format_spec::__format_buffer_hexadecimal_upper_case( + __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first); + + case _Flags::_Type::__scientific_lower_case: + return __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __buffer.__precision(), __first); + + case _Flags::_Type::__scientific_upper_case: + return __format_spec::__format_buffer_scientific_upper_case(__buffer, __value, __buffer.__precision(), __first); + + case _Flags::_Type::__fixed_lower_case: + case _Flags::_Type::__fixed_upper_case: + return __format_spec::__format_buffer_fixed(__buffer, __value, __buffer.__precision(), __first); + + case _Flags::_Type::__general_lower_case: + return __format_spec::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first); + + case _Flags::_Type::__general_upper_case: + return __format_spec::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first); + + default: + _LIBCPP_ASSERT(false, "The parser should have validated the type"); + _LIBCPP_UNREACHABLE(); + } + } +}; + +} //namespace __format_spec + +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; + +# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H diff --git a/lib/libcxx/include/__format/formatter_integer.h b/lib/libcxx/include/__format/formatter_integer.h new file mode 100644 index 0000000000..e1f3d4e348 --- /dev/null +++ b/lib/libcxx/include/__format/formatter_integer.h @@ -0,0 +1,170 @@ +// -*- 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_FORMATTER_INTEGER_H +#define _LIBCPP___FORMAT_FORMATTER_INTEGER_H + +#include <__availability> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +template +class _LIBCPP_TEMPLATE_VIS __parser_integer : public __parser_integral<_CharT> { +public: + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parser_integral<_CharT>::__parse(__parse_ctx); + + switch (this->__type) { + case _Flags::_Type::__default: + this->__type = _Flags::_Type::__decimal; + [[fallthrough]]; + + case _Flags::_Type::__binary_lower_case: + case _Flags::_Type::__binary_upper_case: + case _Flags::_Type::__octal: + case _Flags::_Type::__decimal: + case _Flags::_Type::__hexadecimal_lower_case: + case _Flags::_Type::__hexadecimal_upper_case: + this->__handle_integer(); + break; + + case _Flags::_Type::__char: + this->__handle_char(); + break; + + default: + __throw_format_error("The format-spec type has a type not supported for " + "an integer argument"); + } + return __it; + } +}; + +template +using __formatter_integer = __formatter_integral<__parser_integer<_CharT>>; + +} // namespace __format_spec + +// [format.formatter.spec]/2.3 +// For each charT, for each cv-unqualified arithmetic type ArithmeticT other +// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization + +// Signed integral types. +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +#ifndef _LIBCPP_HAS_NO_INT128 +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter<__int128_t, _CharT> + : public __format_spec::__formatter_integer<_CharT> { + using _Base = __format_spec::__formatter_integer<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(__int128_t __value, auto& __ctx) + -> decltype(__ctx.out()) { + // TODO FMT Implement full 128 bit support. + using _To = long long; + if (__value < numeric_limits<_To>::min() || + __value > numeric_limits<_To>::max()) + __throw_format_error("128-bit value is outside of implemented range"); + + return _Base::format(static_cast<_To>(__value), __ctx); + } +}; +#endif + +// Unsigned integral types. +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_integer<_CharT> {}; +#ifndef _LIBCPP_HAS_NO_INT128 +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter<__uint128_t, _CharT> + : public __format_spec::__formatter_integer<_CharT> { + using _Base = __format_spec::__formatter_integer<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(__uint128_t __value, auto& __ctx) + -> decltype(__ctx.out()) { + // TODO FMT Implement full 128 bit support. + using _To = unsigned long long; + if (__value < numeric_limits<_To>::min() || + __value > numeric_limits<_To>::max()) + __throw_format_error("128-bit value is outside of implemented range"); + + return _Base::format(static_cast<_To>(__value), __ctx); + } +}; +#endif + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_INTEGER_H diff --git a/lib/libcxx/include/__format/formatter_integral.h b/lib/libcxx/include/__format/formatter_integral.h new file mode 100644 index 0000000000..f164ee6109 --- /dev/null +++ b/lib/libcxx/include/__format/formatter_integral.h @@ -0,0 +1,463 @@ +// -*- 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_FORMATTER_INTEGRAL_H +#define _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H + +#include <__algorithm/copy.h> +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/transform.h> +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/formatter.h> +#include <__format/parser_std_format_spec.h> +#include +#include +#include +#include +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#include +#endif + +#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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +/** + * Integral formatting classes. + * + * There are two types used here: + * * C++-type, the type as used in C++. + * * format-type, the output type specified in the std-format-spec. + * + * Design of the integral formatters consists of several layers. + * * @ref __parser_integral The basic std-format-spec parser for all integral + * classes. This parser does the basic sanity checks. It also contains some + * helper functions that are nice to have available for all parsers. + * * A C++-type specific parser. These parsers must derive from + * @ref __parser_integral. Their task is to validate whether the parsed + * std-format-spec is valid for the C++-type and selected format-type. After + * validation they need to make sure all members are properly set. For + * example, when the alignment hasn't changed it needs to set the proper + * default alignment for the format-type. The following parsers are available: + * - @ref __parser_integer + * - @ref __parser_char + * - @ref __parser_bool + * * A general formatter for all integral types @ref __formatter_integral. This + * formatter can handle all formatting of integers and characters. The class + * derives from the proper formatter. + * Note the boolean string format-type isn't supported in this class. + * * A typedef C++-type group combining the @ref __formatter_integral with a + * parser: + * * @ref __formatter_integer + * * @ref __formatter_char + * * @ref __formatter_bool + * * Then every C++-type has its own formatter specializations. They inherit + * from the C++-type group typedef. Most specializations need nothing else. + * Others need some additional specializations in this class. + */ +namespace __format_spec { + +/** Wrapper around @ref to_chars, returning the output pointer. */ +template +_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, + _Tp __value, int __base) { + // 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"); + return __r.ptr; +} + +/** + * Helper to determine the buffer size to output a integer in Base @em x. + * + * There are several overloads for the supported bases. The function uses the + * base as template argument so it can be used in a constant expression. + */ +template +_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept + requires(_Base == 2) { + return numeric_limits<_Tp>::digits // The number of binary digits. + + 2 // Reserve space for the '0[Bb]' prefix. + + 1; // Reserve space for the sign. +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept + requires(_Base == 8) { + return numeric_limits<_Tp>::digits // The number of binary digits. + / 3 // Adjust to octal. + + 1 // Turn floor to ceil. + + 1 // Reserve space for the '0' prefix. + + 1; // Reserve space for the sign. +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept + requires(_Base == 10) { + return numeric_limits<_Tp>::digits10 // The floored value. + + 1 // Turn floor to ceil. + + 1; // Reserve space for the sign. +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept + requires(_Base == 16) { + return numeric_limits<_Tp>::digits // The number of binary digits. + / 4 // Adjust to hexadecimal. + + 2 // Reserve space for the '0[Xx]' prefix. + + 1; // Reserve space for the sign. +} + +/** + * Determines the required grouping based on the size of the input. + * + * The grouping's last element will be repeated. For simplicity this repeating + * is unwrapped based on the length of the input. (When the input is short some + * groups are not processed.) + * + * @returns The size of the groups to write. This means the number of + * separator characters written is size() - 1. + * + * @note Since zero-sized groups cause issues they are silently ignored. + * + * @note The grouping field of the locale is always a @c std::string, + * 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"); + string __r; + auto __end = __grouping.end() - 1; + auto __ptr = __grouping.begin(); + + while (true) { + __size -= *__ptr; + if (__size > 0) + __r.push_back(*__ptr); + else { + // __size <= 0 so the value pushed will be <= *__ptr. + __r.push_back(*__ptr + __size); + return __r; + } + + // Proceed to the next group. + if (__ptr != __end) { + do { + ++__ptr; + // Skip grouping with a width of 0. + } while (*__ptr == 0 && __ptr != __end); + } + } + + _LIBCPP_UNREACHABLE(); +} + +template +requires __formatter::__char_type +class _LIBCPP_TEMPLATE_VIS __formatter_integral : public _Parser { +public: + using _CharT = typename _Parser::char_type; + + template + _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) + -> decltype(__ctx.out()) { + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + + if (this->__type == _Flags::_Type::__char) + return __format_as_char(__value, __ctx); + + if constexpr (unsigned_integral<_Tp>) + return __format_unsigned_integral(__value, false, __ctx); + else { + // Depending on the std-format-spec string the sign and the value + // might not be outputted together: + // - alternate form may insert a prefix string. + // - zero-padding may insert additional '0' characters. + // Therefore the value is processed as a positive unsigned value. + // The function @ref __insert_sign will a '-' when the value was negative. + auto __r = __to_unsigned_like(__value); + bool __negative = __value < 0; + if (__negative) + __r = __complement(__r); + + return __format_unsigned_integral(__r, __negative, __ctx); + } + } + +private: + /** Generic formatting for format-type c. */ + _LIBCPP_HIDE_FROM_ABI auto __format_as_char(integral auto __value, + auto& __ctx) + -> decltype(__ctx.out()) { + if (this->__alignment == _Flags::_Alignment::__default) + this->__alignment = _Flags::_Alignment::__right; + + using _Tp = decltype(__value); + if constexpr (!same_as<_CharT, _Tp>) { + // cmp_less and cmp_greater can't be used for character types. + if constexpr (signed_integral<_CharT> == signed_integral<_Tp>) { + if (__value < numeric_limits<_CharT>::min() || + __value > numeric_limits<_CharT>::max()) + __throw_format_error( + "Integral value outside the range of the char type"); + } else if constexpr (signed_integral<_CharT>) { + // _CharT is signed _Tp is unsigned + if (__value > + static_cast>(numeric_limits<_CharT>::max())) + __throw_format_error( + "Integral value outside the range of the char type"); + } else { + // _CharT is unsigned _Tp is signed + if (__value < 0 || static_cast>(__value) > + numeric_limits<_CharT>::max()) + __throw_format_error( + "Integral value outside the range of the char type"); + } + } + + const auto __c = static_cast<_CharT>(__value); + return __write(_VSTD::addressof(__c), _VSTD::addressof(__c) + 1, + __ctx.out()); + } + + /** + * Generic formatting for format-type bBdoxX. + * + * This small wrapper allocates a buffer with the required size. Then calls + * the real formatter with the buffer and the prefix for the base. + */ + _LIBCPP_HIDE_FROM_ABI auto + __format_unsigned_integral(unsigned_integral auto __value, bool __negative, + auto& __ctx) -> decltype(__ctx.out()) { + switch (this->__type) { + case _Flags::_Type::__binary_lower_case: { + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 2, __ctx, "0b"); + } + case _Flags::_Type::__binary_upper_case: { + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 2, __ctx, "0B"); + } + case _Flags::_Type::__octal: { + // Octal is special; if __value == 0 there's no prefix. + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 8, __ctx, + __value != 0 ? "0" : nullptr); + } + case _Flags::_Type::__decimal: { + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 10, __ctx, nullptr); + } + case _Flags::_Type::__hexadecimal_lower_case: { + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 16, __ctx, "0x"); + } + case _Flags::_Type::__hexadecimal_upper_case: { + array()> __array; + return __format_unsigned_integral(__array.begin(), __array.end(), __value, + __negative, 16, __ctx, "0X"); + } + default: + _LIBCPP_ASSERT(false, "The parser should have validated the type"); + _LIBCPP_UNREACHABLE(); + } + } + + template + requires(same_as || same_as) _LIBCPP_HIDE_FROM_ABI + auto __write(const _Tp* __first, const _Tp* __last, auto __out_it) + -> decltype(__out_it) { + + unsigned __size = __last - __first; + if (this->__type != _Flags::_Type::__hexadecimal_upper_case) [[likely]] { + if (__size >= this->__width) + return _VSTD::copy(__first, __last, _VSTD::move(__out_it)); + + return __formatter::__write(_VSTD::move(__out_it), __first, __last, + __size, this->__width, this->__fill, + this->__alignment); + } + + // this->__type == _Flags::_Type::__hexadecimal_upper_case + // This means all characters in the range [a-f] need to be changed to their + // uppercase representation. The transformation is done as transformation + // in the output routine instead of before. This avoids another pass over + // the data. + // TODO FMT See whether it's possible to do this transformation during the + // conversion. (This probably requires changing std::to_chars' alphabet.) + if (__size >= this->__width) + return _VSTD::transform(__first, __last, _VSTD::move(__out_it), + __hex_to_upper); + + return __formatter::__write(_VSTD::move(__out_it), __first, __last, __size, + __hex_to_upper, this->__width, this->__fill, + this->__alignment); + } + + _LIBCPP_HIDE_FROM_ABI auto + __format_unsigned_integral(char* __begin, char* __end, + unsigned_integral auto __value, bool __negative, + int __base, auto& __ctx, const char* __prefix) + -> decltype(__ctx.out()) { + char* __first = __insert_sign(__begin, __negative, this->__sign); + if (this->__alternate_form && __prefix) + while (*__prefix) + *__first++ = *__prefix++; + + char* __last = __to_buffer(__first, __end, __value, __base); +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (this->__locale_specific_form) { + const auto& __np = use_facet>(__ctx.locale()); + string __grouping = __np.grouping(); + ptrdiff_t __size = __last - __first; + // Writing the grouped form has more overhead than the normal output + // routines. If there will be no separators written the locale-specific + // form is identical to the normal routine. Test whether to grouped form + // is required. + if (!__grouping.empty() && __size > __grouping[0]) + return __format_grouping(__ctx.out(), __begin, __first, __last, + __determine_grouping(__size, __grouping), + __np.thousands_sep()); + } +#endif + auto __out_it = __ctx.out(); + if (this->__alignment != _Flags::_Alignment::__default) + __first = __begin; + else { + // __buf contains [sign][prefix]data + // ^ location of __first + // The zero padding is done like: + // - Write [sign][prefix] + // - Write data right aligned with '0' as fill character. + __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it)); + this->__alignment = _Flags::_Alignment::__right; + this->__fill = _CharT('0'); + uint32_t __size = __first - __begin; + this->__width -= _VSTD::min(__size, this->__width); + } + + return __write(__first, __last, _VSTD::move(__out_it)); + } + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION + /** Format's the locale-specific form's groupings. */ + template + _LIBCPP_HIDE_FROM_ABI _OutIt + __format_grouping(_OutIt __out_it, const char* __begin, const char* __first, + const char* __last, string&& __grouping, _CharT __sep) { + + // TODO FMT This function duplicates some functionality of the normal + // output routines. Evaluate whether these parts can be efficiently + // combined with the existing routines. + + unsigned __size = (__first - __begin) + // [sign][prefix] + (__last - __first) + // data + (__grouping.size() - 1); // number of separator characters + + __formatter::__padding_size_result __padding = {0, 0}; + if (this->__alignment == _Flags::_Alignment::__default) { + // Write [sign][prefix]. + __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it)); + + if (this->__width > __size) { + // Write zero padding. + __padding.__before = this->__width - __size; + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), this->__width - __size, + _CharT('0')); + } + } else { + if (this->__width > __size) { + // Determine padding and write padding. + __padding = __formatter::__padding_size(__size, this->__width, + this->__alignment); + + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, + this->__fill); + } + // Write [sign][prefix]. + __out_it = _VSTD::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 `this->__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 (this->__type == _Flags::_Type::__hexadecimal_upper_case) { + __last = __first + *__r; + __out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it), + __hex_to_upper); + __first = __last; + } else { + __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + } + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, + this->__fill); + } +#endif // _LIBCPP_HAS_NO_LOCALIZATION +}; + +} // namespace __format_spec + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H diff --git a/lib/libcxx/include/__format/formatter_pointer.h b/lib/libcxx/include/__format/formatter_pointer.h new file mode 100644 index 0000000000..aa2eb641c6 --- /dev/null +++ b/lib/libcxx/include/__format/formatter_pointer.h @@ -0,0 +1,91 @@ +// -*- 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_FORMATTER_POINTER_H +#define _LIBCPP___FORMAT_FORMATTER_POINTER_H + +#include <__algorithm/copy.h> +#include <__availability> +#include <__config> +#include <__debug> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/access.h> +#include <__nullptr> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +# if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +template <__formatter::__char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatter_pointer : public __parser_pointer<_CharT> { +public: + _LIBCPP_HIDE_FROM_ABI auto format(const void* __ptr, auto& __ctx) -> decltype(__ctx.out()) { + _LIBCPP_ASSERT(this->__alignment != _Flags::_Alignment::__default, + "The call to parse should have updated the alignment"); + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + + // This code looks a lot like the code to format a hexadecimal integral, + // but that code isn't public. Making that code public requires some + // refactoring. + // TODO FMT Remove code duplication. + char __buffer[2 + 2 * sizeof(uintptr_t)]; + __buffer[0] = '0'; + __buffer[1] = 'x'; + char* __last = __to_buffer(__buffer + 2, _VSTD::end(__buffer), reinterpret_cast(__ptr), 16); + + unsigned __size = __last - __buffer; + if (__size >= this->__width) + return _VSTD::copy(__buffer, __last, __ctx.out()); + + return __formatter::__write(__ctx.out(), __buffer, __last, __size, this->__width, this->__fill, this->__alignment); + } +}; + +} // namespace __format_spec + +// [format.formatter.spec]/2.4 +// For each charT, the pointer type specializations template<> +// - struct formatter; +// - template<> struct formatter; +// - template<> struct formatter; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_pointer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_pointer<_CharT> {}; +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_pointer<_CharT> {}; + +# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_POINTER_H diff --git a/lib/libcxx/include/__format/formatter_string.h b/lib/libcxx/include/__format/formatter_string.h new file mode 100644 index 0000000000..04950faa4a --- /dev/null +++ b/lib/libcxx/include/__format/formatter_string.h @@ -0,0 +1,162 @@ +// -*- 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_FORMATTER_STRING_H +#define _LIBCPP___FORMAT_FORMATTER_STRING_H + +#include <__config> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_string.h> +#include <__format/formatter.h> +#include <__format/parser_std_format_spec.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 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +template <__formatter::__char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatter_string : public __parser_string<_CharT> { +public: + _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, + auto& __ctx) -> decltype(__ctx.out()) { + + _LIBCPP_ASSERT(this->__alignment != _Flags::_Alignment::__default, + "The parser should not use these defaults"); + + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + + if (this->__precision_needs_substitution()) + this->__substitute_precision_arg_id(__ctx.arg(this->__precision)); + + return __formatter::__write_unicode( + __ctx.out(), __str, this->__width, + this->__has_precision_field() ? this->__precision : -1, this->__fill, + this->__alignment); + } +}; + +} //namespace __format_spec + +// [format.formatter.spec]/2.2 For each charT, the string type specializations + +// Formatter const char*. +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_string<_CharT> { + using _Base = __format_spec::__formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(const _CharT* __str, auto& __ctx) + -> decltype(__ctx.out()) { + _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " + "prevented an invalid pointer."); + + // When using a center or right alignment and the width option the length + // of __str must be known to add the padding upfront. This case is handled + // by the base class by converting the argument to a basic_string_view. + // + // When using left alignment and the width option the padding is added + // after outputting __str so the length can be determined while outputting + // __str. The same holds true for the precision, during outputting __str it + // can be validated whether the precision threshold has been reached. For + // now these optimizations aren't implemented. Instead the base class + // handles these options. + // TODO FMT Implement these improvements. + if (this->__has_width_field() || this->__has_precision_field()) + return _Base::format(__str, __ctx); + + // No formatting required, copy the string to the output. + auto __out_it = __ctx.out(); + while (*__str) + *__out_it++ = *__str++; + return __out_it; + } +}; + +// Formatter char*. +template <__formatter::__char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter<_CharT*, _CharT> : public formatter { + using _Base = formatter; + + _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) + -> decltype(__ctx.out()) { + return _Base::format(__str, __ctx); + } +}; + +// Formatter const char[]. +template <__formatter::__char_type _CharT, size_t _Size> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter + : public __format_spec::__formatter_string<_CharT> { + using _Base = __format_spec::__formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) + -> decltype(__ctx.out()) { + return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); + } +}; + +// Formatter std::string. +template <__formatter::__char_type _CharT, class _Traits, class _Allocator> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + formatter, _CharT> + : public __format_spec::__formatter_string<_CharT> { + using _Base = __format_spec::__formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto + format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) + -> decltype(__ctx.out()) { + // drop _Traits and _Allocator + return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); + } +}; + +// Formatter std::string_view. +template <__formatter::__char_type _CharT, class _Traits> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter, _CharT> + : public __format_spec::__formatter_string<_CharT> { + using _Base = __format_spec::__formatter_string<_CharT>; + + _LIBCPP_HIDE_FROM_ABI auto + format(basic_string_view<_CharT, _Traits> __str, auto& __ctx) + -> decltype(__ctx.out()) { + // drop _Traits + return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); + } +}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_FORMATTER_STRING_H diff --git a/lib/libcxx/include/__format/parser_std_format_spec.h b/lib/libcxx/include/__format/parser_std_format_spec.h new file mode 100644 index 0000000000..9d893e9ced --- /dev/null +++ b/lib/libcxx/include/__format/parser_std_format_spec.h @@ -0,0 +1,1398 @@ +// -*- 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_PARSER_STD_FORMAT_SPEC_H +#define _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H + +#include <__algorithm/find_if.h> +#include <__algorithm/min.h> +#include <__config> +#include <__debug> +#include <__format/format_arg.h> +#include <__format/format_error.h> +#include <__format/format_string.h> +#include <__variant/monostate.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 > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +# if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +/** + * Contains the flags for the std-format-spec. + * + * Some format-options can only be used for specific C++types and may depend on + * the selected format-type. + * * The C++type filtering can be done using the proper policies for + * @ref __parser_std. + * * The format-type filtering needs to be done post parsing in the parser + * derived from @ref __parser_std. + */ +class _LIBCPP_TYPE_VIS _Flags { +public: + enum class _LIBCPP_ENUM_VIS _Alignment : uint8_t { + /** + * No alignment is set in the format string. + * + * Zero-padding is ignored when an alignment is selected. + * The default alignment depends on the selected format-type. + */ + __default, + __left, + __center, + __right + }; + enum class _LIBCPP_ENUM_VIS _Sign : uint8_t { + /** + * No sign is set in the format string. + * + * The sign isn't allowed for certain format-types. By using this value + * it's possible to detect whether or not the user explicitly set the sign + * flag. For formatting purposes it behaves the same as @ref __minus. + */ + __default, + __minus, + __plus, + __space + }; + + _Alignment __alignment : 2 {_Alignment::__default}; + _Sign __sign : 2 {_Sign::__default}; + uint8_t __alternate_form : 1 {false}; + uint8_t __zero_padding : 1 {false}; + uint8_t __locale_specific_form : 1 {false}; + + enum class _LIBCPP_ENUM_VIS _Type : uint8_t { + __default, + __string, + __binary_lower_case, + __binary_upper_case, + __octal, + __decimal, + __hexadecimal_lower_case, + __hexadecimal_upper_case, + __pointer, + __char, + __float_hexadecimal_lower_case, + __float_hexadecimal_upper_case, + __scientific_lower_case, + __scientific_upper_case, + __fixed_lower_case, + __fixed_upper_case, + __general_lower_case, + __general_upper_case + }; + + _Type __type{_Type::__default}; +}; + +namespace __detail { +template +_LIBCPP_HIDE_FROM_ABI constexpr bool +__parse_alignment(_CharT __c, _Flags& __flags) noexcept { + switch (__c) { + case _CharT('<'): + __flags.__alignment = _Flags::_Alignment::__left; + return true; + + case _CharT('^'): + __flags.__alignment = _Flags::_Alignment::__center; + return true; + + case _CharT('>'): + __flags.__alignment = _Flags::_Alignment::__right; + return true; + } + return false; +} +} // namespace __detail + +template +class _LIBCPP_TEMPLATE_VIS __parser_fill_align { +public: + // TODO FMT The standard doesn't specify this character is a Unicode + // character. Validate what fmt and MSVC have implemented. + _CharT __fill{_CharT(' ')}; + +protected: + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* + __parse(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"); + if (__begin + 1 != __end) { + if (__detail::__parse_alignment(*(__begin + 1), __flags)) { + if (*__begin == _CharT('{') || *__begin == _CharT('}')) + __throw_format_error( + "The format-spec fill field contains an invalid character"); + __fill = *__begin; + return __begin + 2; + } + } + + if (__detail::__parse_alignment(*__begin, __flags)) + return __begin + 1; + + return __begin; + } +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__parse_sign(const _CharT* __begin, _Flags& __flags) noexcept { + switch (*__begin) { + case _CharT('-'): + __flags.__sign = _Flags::_Sign::__minus; + break; + case _CharT('+'): + __flags.__sign = _Flags::_Sign::__plus; + break; + case _CharT(' '): + __flags.__sign = _Flags::_Sign::__space; + break; + default: + return __begin; + } + return __begin + 1; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__parse_alternate_form(const _CharT* __begin, _Flags& __flags) noexcept { + if (*__begin == _CharT('#')) { + __flags.__alternate_form = true; + ++__begin; + } + + return __begin; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__parse_zero_padding(const _CharT* __begin, _Flags& __flags) noexcept { + if (*__begin == _CharT('0')) { + __flags.__zero_padding = true; + ++__begin; + } + + return __begin; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> +__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + // 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) + __throw_format_error("End of input while parsing format-spec arg-id"); + + __format::__parse_number_result __r = + __format::__parse_arg_id(__begin, __end, __parse_ctx); + + if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) + __throw_format_error("Invalid arg-id"); + + ++__r.__ptr; + return __r; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr uint32_t +__substitute_arg_id(basic_format_arg<_Context> __arg) { + return visit_format_arg( + [](auto __arg) -> uint32_t { + using _Type = decltype(__arg); + if constexpr (integral<_Type>) { + if constexpr (signed_integral<_Type>) { + if (__arg < 0) + __throw_format_error("A format-spec arg-id replacement shouldn't " + "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)) + __throw_format_error("A format-spec arg-id replacement exceeds " + "the maximum supported value"); + + return __arg; + } else if constexpr (same_as<_Type, monostate>) + __throw_format_error("Argument index out of bounds"); + else + __throw_format_error("A format-spec arg-id replacement argument " + "isn't an integral type"); + }, + __arg); +} + +class _LIBCPP_TYPE_VIS __parser_width { +public: + /** Contains a width or an arg-id. */ + uint32_t __width : 31 {0}; + /** Determines whether the value stored is a width or an arg-id. */ + uint32_t __width_as_arg : 1 {0}; + +protected: + /** + * Does the supplied std-format-spec contain a width field? + * + * When the field isn't present there's no padding required. This can be used + * to optimize the formatting. + */ + constexpr bool __has_width_field() const noexcept { + return __width_as_arg || __width; + } + + /** + * Does the supplied width field contain an arg-id? + * + * If @c true the formatter needs to call @ref __substitute_width_arg_id. + */ + constexpr bool __width_needs_substitution() const noexcept { + return __width_as_arg; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* + __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + if (*__begin == _CharT('0')) + __throw_format_error( + "A format-spec width field shouldn't have a leading zero"); + + if (*__begin == _CharT('{')) { + __format::__parse_number_result __r = + __parse_arg_id(++__begin, __end, __parse_ctx); + __width = __r.__value; + __width_as_arg = 1; + return __r.__ptr; + } + + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + return __begin; + + __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"); + return __r.__ptr; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_width_arg_id(auto __arg) { + _LIBCPP_ASSERT(__width_as_arg == 1, + "Substitute width called when no substitution is required"); + + // The clearing of the flag isn't required but looks better when debugging + // the code. + __width_as_arg = 0; + __width = __substitute_arg_id(__arg); + if (__width == 0) + __throw_format_error( + "A format-spec width field replacement should have a positive value"); + } +}; + +class _LIBCPP_TYPE_VIS __parser_precision { +public: + /** Contains a precision or an arg-id. */ + uint32_t __precision : 31 {__format::__number_max}; + /** + * Determines whether the value stored is a precision or an arg-id. + * + * @note Since @ref __precision == @ref __format::__number_max is a valid + * value, the default value contains an arg-id of INT32_MAX. (This number of + * arguments isn't supported by compilers.) This is used to detect whether + * the std-format-spec contains a precision field. + */ + uint32_t __precision_as_arg : 1 {1}; + +protected: + /** + * Does the supplied std-format-spec contain a precision field? + * + * When the field isn't present there's no truncating required. This can be + * used to optimize the formatting. + */ + constexpr bool __has_precision_field() const noexcept { + + return __precision_as_arg == 0 || // Contains a value? + __precision != __format::__number_max; // The arg-id is valid? + } + + /** + * Does the supplied precision field contain an arg-id? + * + * If @c true the formatter needs to call @ref __substitute_precision_arg_id. + */ + constexpr bool __precision_needs_substitution() const noexcept { + return __precision_as_arg && __precision != __format::__number_max; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* + __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { + if (*__begin != _CharT('.')) + return __begin; + + ++__begin; + if (__begin == __end) + __throw_format_error("End of input while parsing format-spec precision"); + + if (*__begin == _CharT('{')) { + __format::__parse_number_result __arg_id = + __parse_arg_id(++__begin, __end, __parse_ctx); + _LIBCPP_ASSERT(__arg_id.__value != __format::__number_max, + "Unsupported number of arguments, since this number of " + "arguments is used a special value"); + __precision = __arg_id.__value; + return __arg_id.__ptr; + } + + if (*__begin < _CharT('0') || *__begin > _CharT('9')) + __throw_format_error( + "The format-spec precision field doesn't contain a value or arg-id"); + + __format::__parse_number_result __r = + __format::__parse_number(__begin, __end); + __precision = __r.__value; + __precision_as_arg = 0; + return __r.__ptr; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_precision_arg_id( + auto __arg) { + _LIBCPP_ASSERT( + __precision_as_arg == 1 && __precision != __format::__number_max, + "Substitute precision called when no substitution is required"); + + // The clearing of the flag isn't required but looks better when debugging + // the code. + __precision_as_arg = 0; + __precision = __substitute_arg_id(__arg); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__parse_locale_specific_form(const _CharT* __begin, _Flags& __flags) noexcept { + if (*__begin == _CharT('L')) { + __flags.__locale_specific_form = true; + ++__begin; + } + + return __begin; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__parse_type(const _CharT* __begin, _Flags& __flags) { + + // 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 + // been parsed. So its easier to implement the validation for all types in + // the specific parse function. + switch (*__begin) { + case 'A': + __flags.__type = _Flags::_Type::__float_hexadecimal_upper_case; + break; + case 'B': + __flags.__type = _Flags::_Type::__binary_upper_case; + break; + case 'E': + __flags.__type = _Flags::_Type::__scientific_upper_case; + break; + case 'F': + __flags.__type = _Flags::_Type::__fixed_upper_case; + break; + case 'G': + __flags.__type = _Flags::_Type::__general_upper_case; + break; + case 'X': + __flags.__type = _Flags::_Type::__hexadecimal_upper_case; + break; + case 'a': + __flags.__type = _Flags::_Type::__float_hexadecimal_lower_case; + break; + case 'b': + __flags.__type = _Flags::_Type::__binary_lower_case; + break; + case 'c': + __flags.__type = _Flags::_Type::__char; + break; + case 'd': + __flags.__type = _Flags::_Type::__decimal; + break; + case 'e': + __flags.__type = _Flags::_Type::__scientific_lower_case; + break; + case 'f': + __flags.__type = _Flags::_Type::__fixed_lower_case; + break; + case 'g': + __flags.__type = _Flags::_Type::__general_lower_case; + break; + case 'o': + __flags.__type = _Flags::_Type::__octal; + break; + case 'p': + __flags.__type = _Flags::_Type::__pointer; + break; + case 's': + __flags.__type = _Flags::_Type::__string; + break; + case 'x': + __flags.__type = _Flags::_Type::__hexadecimal_lower_case; + break; + default: + return __begin; + } + return ++__begin; +} + +/** + * Process the parsed alignment and zero-padding state of arithmetic types. + * + * [format.string.std]/13 + * If the 0 character and an align option both appear, the 0 character is + * ignored. + * + * For the formatter a @ref __default alignment means zero-padding. + */ +_LIBCPP_HIDE_FROM_ABI constexpr void __process_arithmetic_alignment(_Flags& __flags) { + __flags.__zero_padding &= __flags.__alignment == _Flags::_Alignment::__default; + if (!__flags.__zero_padding && __flags.__alignment == _Flags::_Alignment::__default) + __flags.__alignment = _Flags::_Alignment::__right; +} + +/** + * The parser for the std-format-spec. + * + * [format.string.std]/1 specifies the std-format-spec: + * fill-and-align sign # 0 width precision L type + * + * All these fields are optional. Whether these fields can be used depend on: + * - The type supplied to the format string. + * E.g. A string never uses the sign field so the field may not be set. + * This constrain is validated by the parsers in this file. + * - The supplied value for the optional type field. + * E.g. A int formatted as decimal uses the sign field. + * When formatted as a char the sign field may no longer be set. + * This constrain isn't validated by the parsers in this file. + * + * The base classes are ordered to minimize the amount of padding. + * + * This implements the parser for the string types. + */ +template +class _LIBCPP_TEMPLATE_VIS __parser_string + : public __parser_width, // provides __width(|as_arg) + public __parser_precision, // provides __precision(|as_arg) + public __parser_fill_align<_CharT>, // provides __fill and uses __flags + public _Flags // provides __flags +{ +public: + using char_type = _CharT; + + _LIBCPP_HIDE_FROM_ABI constexpr __parser_string() { + this->__alignment = _Flags::_Alignment::__left; + } + + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parse(__parse_ctx); + __process_display_type(); + return __it; + } + +private: + /** + * Parses the std-format-spec. + * + * @throws __throw_format_error When @a __parse_ctx contains an ill-formed + * std-format-spec. + * + * @returns An iterator to the end of input or point at the closing '}'. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, + static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parser_width::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = __parser_precision::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); + + if (__begin != __end && *__begin != _CharT('}')) + __throw_format_error( + "The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + /** Processes the parsed std-format-spec based on the parsed display type. */ + _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { + switch (this->__type) { + case _Flags::_Type::__default: + case _Flags::_Type::__string: + break; + + default: + __throw_format_error("The format-spec type has a type not supported for " + "a string argument"); + } + } +}; + +/** + * The parser for the std-format-spec. + * + * This implements the parser for the integral types. This includes the + * character type and boolean type. + * + * See @ref __parser_string. + */ +template +class _LIBCPP_TEMPLATE_VIS __parser_integral + : public __parser_width, // provides __width(|as_arg) + public __parser_fill_align<_CharT>, // provides __fill and uses __flags + public _Flags // provides __flags +{ +public: + using char_type = _CharT; + +protected: + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, + static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_sign(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parser_width::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = + __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); + + if (__begin != __end && *__begin != _CharT('}')) + __throw_format_error( + "The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + /** Handles the post-parsing updates for the integer types. */ + _LIBCPP_HIDE_FROM_ABI constexpr void __handle_integer() noexcept { + __process_arithmetic_alignment(static_cast<_Flags&>(*this)); + } + + /** + * Handles the post-parsing updates for the character types. + * + * Sets the alignment and validates the format flags set for a character type. + * + * At the moment the validation for a character and a Boolean behave the + * same, but this may change in the future. + * Specifically at the moment the locale-specific form is allowed for the + * char output type, but it has no effect on the output. + */ + _LIBCPP_HIDE_FROM_ABI constexpr void __handle_char() { __handle_bool(); } + + /** + * Handles the post-parsing updates for the Boolean types. + * + * Sets the alignment and validates the format flags set for a Boolean type. + */ + _LIBCPP_HIDE_FROM_ABI constexpr void __handle_bool() { + if (this->__sign != _Flags::_Sign::__default) + __throw_format_error("A sign field isn't allowed in this format-spec"); + + if (this->__alternate_form) + __throw_format_error( + "An alternate form field isn't allowed in this format-spec"); + + if (this->__zero_padding) + __throw_format_error( + "A zero-padding field isn't allowed in this format-spec"); + + if (this->__alignment == _Flags::_Alignment::__default) + this->__alignment = _Flags::_Alignment::__left; + } +}; + +/** + * The parser for the std-format-spec. + * + * This implements the parser for the floating-point types. + * + * See @ref __parser_string. + */ +template +class _LIBCPP_TEMPLATE_VIS __parser_floating_point + : public __parser_width, // provides __width(|as_arg) + public __parser_precision, // provides __precision(|as_arg) + public __parser_fill_align<_CharT>, // provides __fill and uses __flags + public _Flags // provides __flags +{ +public: + using char_type = _CharT; + + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parse(__parse_ctx); + __process_arithmetic_alignment(static_cast<_Flags&>(*this)); + __process_display_type(); + return __it; + } +protected: + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, + static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_sign(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parser_width::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = __parser_precision::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = + __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); + + if (__begin != __end && *__begin != _CharT('}')) + __throw_format_error( + "The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + /** Processes the parsed std-format-spec based on the parsed display type. */ + _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { + switch (this->__type) { + case _Flags::_Type::__default: + // When no precision specified then it keeps default since that + // formatting differs from the other types. + if (this->__has_precision_field()) + this->__type = _Flags::_Type::__general_lower_case; + break; + case _Flags::_Type::__float_hexadecimal_lower_case: + case _Flags::_Type::__float_hexadecimal_upper_case: + // Precision specific behavior will be handled later. + break; + case _Flags::_Type::__scientific_lower_case: + case _Flags::_Type::__scientific_upper_case: + case _Flags::_Type::__fixed_lower_case: + case _Flags::_Type::__fixed_upper_case: + case _Flags::_Type::__general_lower_case: + case _Flags::_Type::__general_upper_case: + if (!this->__has_precision_field()) { + // Set the default precision for the call to to_chars. + this->__precision = 6; + this->__precision_as_arg = false; + } + break; + + default: + __throw_format_error("The format-spec type has a type not supported for " + "a floating-point argument"); + } + } +}; + +/** + * The parser for the std-format-spec. + * + * This implements the parser for the pointer types. + * + * See @ref __parser_string. + */ +template +class _LIBCPP_TEMPLATE_VIS __parser_pointer : public __parser_width, // provides __width(|as_arg) + public __parser_fill_align<_CharT>, // provides __fill and uses __flags + public _Flags // provides __flags +{ +public: + using char_type = _CharT; + + _LIBCPP_HIDE_FROM_ABI constexpr __parser_pointer() { + // Implements LWG3612 Inconsistent pointer alignment in std::format. + // The issue's current status is "Tentatively Ready" and libc++ status is + // still experimental. + // + // TODO FMT Validate this with the final resolution of LWG3612. + this->__alignment = _Flags::_Alignment::__right; + } + + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __it = __parse(__parse_ctx); + __process_display_type(); + return __it; + } + +protected: + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + // An integer presentation type isn't defined in the Standard. + // Since a pointer is formatted as an integer it can be argued it's an + // integer presentation type. However there are two LWG-issues asserting it + // isn't an integer presentation type: + // - LWG3612 Inconsistent pointer alignment in std::format + // - LWG3644 std::format does not define "integer presentation type" + // + // There's a paper to make additional clarifications on the status of + // formatting pointers and proposes additional fields to be valid. That + // paper hasn't been reviewed by the Committee yet. + // - P2510 Formatting pointers + // + // The current implementation assumes formatting pointers isn't covered by + // "integer presentation type". + // TODO FMT Apply the LWG-issues/papers after approval/rejection by the Committee. + + __begin = __parser_width::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); + + if (__begin != __end && *__begin != _CharT('}')) + __throw_format_error("The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + /** Processes the parsed std-format-spec based on the parsed display type. */ + _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { + switch (this->__type) { + case _Flags::_Type::__default: + this->__type = _Flags::_Type::__pointer; + break; + case _Flags::_Type::__pointer: + break; + default: + __throw_format_error("The format-spec type has a type not supported for a pointer argument"); + } + } +}; + +/** Helper struct returned from @ref __get_string_alignment. */ +template +struct _LIBCPP_TEMPLATE_VIS __string_alignment { + /** Points beyond the last character to write to the output. */ + const _CharT* __last; + /** + * The estimated number of columns in the output or 0. + * + * Only when the output needs to be aligned it's required to know the exact + * number of columns in the output. So if the formatted output has only a + * minimum width the exact size isn't important. It's only important to know + * the minimum has been reached. The minimum width is the width specified in + * the format-spec. + * + * For example in this code @code std::format("{:10}", MyString); @endcode + * the width estimation can stop once the algorithm has determined the output + * width is 10 columns. + * + * So if: + * * @ref __align == @c true the @ref __size is the estimated number of + * columns required. + * * @ref __align == @c false the @ref __size is the estimated number of + * columns required or 0 when the estimation algorithm stopped prematurely. + */ + ptrdiff_t __size; + /** + * Does the output need to be aligned. + * + * When alignment is needed the output algorithm needs to add the proper + * padding. Else the output algorithm just needs to copy the input up to + * @ref __last. + */ + bool __align; +}; + +#ifndef _LIBCPP_HAS_NO_UNICODE +namespace __detail { + +/** + * Unicode column width estimates. + * + * Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. + * Depending on format the relation between the number of code units stored and + * the number of output columns differs. The first relation is the number of + * code units forming a code point. (The text assumes the code units are + * unsigned.) + * - UTF-8 The number of code units is between one and four. The first 127 + * Unicode code points match the ASCII character set. When the highest bit is + * set it means the code point has more than one code unit. + * - UTF-16: The number of code units is between 1 and 2. When the first + * code unit is in the range [0xd800,0xdfff) it means the code point uses two + * code units. + * - UTF-32: The number of code units is always one. + * + * The code point to the number of columns isn't well defined. The code uses the + * estimations defined in [format.string.std]/11. This list might change in the + * future. + * + * The algorithm of @ref __get_string_alignment uses two different scanners: + * - The simple scanner @ref __estimate_column_width_fast. This scanner assumes + * 1 code unit is 1 column. This scanner stops when it can't be sure the + * assumption is valid: + * - UTF-8 when the code point is encoded in more than 1 code unit. + * - UTF-16 and UTF-32 when the first multi-column code point is encountered. + * (The code unit's value is lower than 0xd800 so the 2 code unit encoding + * is irrelevant for this scanner.) + * Due to these assumptions the scanner is faster than the full scanner. It + * can process all text only containing ASCII. For UTF-16/32 it can process + * most (all?) European languages. (Note the set it can process might be + * reduced in the future, due to updates in the scanning rules.) + * - The full scanner @ref __estimate_column_width. This scanner, if needed, + * converts multiple code units into one code point then converts the code + * point to a column width. + * + * See also: + * - [format.string.general]/11 + * - https://en.wikipedia.org/wiki/UTF-8#Encoding + * - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + */ + +/** + * The first 2 column code point. + * + * This is the point where the fast UTF-16/32 scanner needs to stop processing. + */ +inline constexpr uint32_t __two_column_code_point = 0x1100; + +/** Helper concept for an UTF-8 character type. */ +template +concept __utf8_character = same_as<_CharT, char> || same_as<_CharT, char8_t>; + +/** Helper concept for an UTF-16 character type. */ +template +concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) || same_as<_CharT, char16_t>; + +/** Helper concept for an UTF-32 character type. */ +template +concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) || same_as<_CharT, char32_t>; + +/** Helper concept for an UTF-16 or UTF-32 character type. */ +template +concept __utf16_or_32_character = __utf16_character<_CharT> || __utf32_character<_CharT>; + +/** + * 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 inline constexpr int __column_width_3(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c < 0x1'0000, + "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 inline constexpr int __column_width_4(uint32_t __c) noexcept { + _LIBCPP_ASSERT(__c >= 0x1'0000, + "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 inline constexpr int __column_width(uint32_t __c) noexcept { + if (__c < 0x1'0000) + return __column_width_3(__c); + + return __column_width_4(__c); +} + +/** + * Estimate the column width for the UTF-8 sequence using the fast algorithm. + */ +template <__utf8_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__estimate_column_width_fast(const _CharT* __first, + const _CharT* __last) noexcept { + return _VSTD::find_if(__first, __last, + [](unsigned char __c) { return __c & 0x80; }); +} + +/** + * @overload + * + * The implementation for UTF-16/32. + */ +template <__utf16_or_32_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* +__estimate_column_width_fast(const _CharT* __first, + const _CharT* __last) noexcept { + return _VSTD::find_if(__first, __last, + [](uint32_t __c) { return __c >= 0x1100; }); +} + +template +struct _LIBCPP_TEMPLATE_VIS __column_width_result { + /** The number of output columns. */ + size_t __width; + /** + * The last parsed element. + * + * This limits the original output to fit in the wanted number of columns. + */ + const _CharT* __ptr; +}; + +/** + * Small helper to determine the width of malformed Unicode. + * + * @note This function's only needed for UTF-8. During scanning UTF-8 there + * are multiple place where it can be detected that the Unicode is malformed. + * UTF-16 only requires 1 test and UTF-32 requires no testing. + */ +template <__utf8_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width_malformed(const _CharT* __first, const _CharT* __last, + size_t __maximum, size_t __result) noexcept { + size_t __size = __last - __first; + size_t __n = _VSTD::min(__size, __maximum); + return {__result + __n, __first + __n}; +} + +/** + * Determines the number of output columns needed to render the input. + * + * @note When the scanner encounters malformed Unicode it acts as-if every code + * unit at the end of the input is one output column. It's expected the output + * terminal will replace these malformed code units with a one column + * replacement characters. + * + * @param __first Points to the first element of the input range. + * @param __last Points beyond the last element of the input range. + * @param __maximum The maximum number of output columns. The returned number + * of estimated output columns will not exceed this value. + */ +template <__utf8_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width(const _CharT* __first, const _CharT* __last, + size_t __maximum) noexcept { + size_t __result = 0; + + while (__first != __last) { + // 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: // 1-code unit encoding: all 1 column + ++__result; + ++__first; + break; + + case 2: // 2-code unit encoding: all 1 column + // Malformed Unicode. + if (__last - __first < 2) [[unlikely]] + return __estimate_column_width_malformed(__first, __last, __maximum, + __result); + __first += 2; + ++__result; + break; + + case 3: // 3-code unit encoding: either 1 or 2 columns + // Malformed Unicode. + if (__last - __first < 3) [[unlikely]] + return __estimate_column_width_malformed(__first, __last, __maximum, + __result); + { + uint32_t __c = static_cast(*__first++) & 0x0f; + __c <<= 6; + __c |= static_cast(*__first++) & 0x3f; + __c <<= 6; + __c |= static_cast(*__first++) & 0x3f; + __result += __column_width_3(__c); + if (__result > __maximum) + return {__result - 2, __first - 3}; + } + break; + case 4: // 4-code unit encoding: either 1 or 2 columns + // Malformed Unicode. + if (__last - __first < 4) [[unlikely]] + return __estimate_column_width_malformed(__first, __last, __maximum, + __result); + { + uint32_t __c = static_cast(*__first++) & 0x07; + __c <<= 6; + __c |= static_cast(*__first++) & 0x3f; + __c <<= 6; + __c |= static_cast(*__first++) & 0x3f; + __c <<= 6; + __c |= static_cast(*__first++) & 0x3f; + __result += __column_width_4(__c); + if (__result > __maximum) + return {__result - 2, __first - 4}; + } + break; + default: + // Malformed Unicode. + return __estimate_column_width_malformed(__first, __last, __maximum, + __result); + } + + if (__result >= __maximum) + return {__result, __first}; + } + return {__result, __first}; +} + +template <__utf16_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width(const _CharT* __first, const _CharT* __last, + size_t __maximum) noexcept { + size_t __result = 0; + + while (__first != __last) { + uint32_t __c = *__first; + // Is the code unit part of a surrogate pair? See + // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + if (__c >= 0xd800 && __c <= 0xDfff) { + // Malformed Unicode. + if (__last - __first < 2) [[unlikely]] + return {__result + 1, __first + 1}; + + __c -= 0xd800; + __c <<= 10; + __c += (*(__first + 1) - 0xdc00); + __c += 0x10'000; + + __result += __column_width_4(__c); + if (__result > __maximum) + return {__result - 2, __first}; + __first += 2; + } else { + __result += __column_width_3(__c); + if (__result > __maximum) + return {__result - 2, __first}; + ++__first; + } + + if (__result >= __maximum) + return {__result, __first}; + } + + return {__result, __first}; +} + +template <__utf32_character _CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +__estimate_column_width(const _CharT* __first, const _CharT* __last, + size_t __maximum) noexcept { + size_t __result = 0; + + while (__first != __last) { + wchar_t __c = *__first; + __result += __column_width(__c); + + if (__result > __maximum) + return {__result - 2, __first}; + + ++__first; + if (__result >= __maximum) + return {__result, __first}; + } + + return {__result, __first}; +} + +} // namespace __detail + +template +_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> +__get_string_alignment(const _CharT* __first, const _CharT* __last, + ptrdiff_t __width, ptrdiff_t __precision) noexcept { + _LIBCPP_ASSERT(__width != 0 || __precision != -1, + "The function has no effect and shouldn't be used"); + + // TODO FMT There might be more optimizations possible: + // If __precision == __format::__number_max and the encoding is: + // * UTF-8 : 4 * (__last - __first) >= __width + // * UTF-16 : 2 * (__last - __first) >= __width + // * UTF-32 : (__last - __first) >= __width + // In these cases it's certain the output is at least the requested width. + // It's unknown how often this happens in practice. For now the improvement + // isn't implemented. + + /* + * First assume there are no special Unicode code units in the input. + * - Apply the precision (this may reduce the size of the input). When + * __precison == -1 this step is omitted. + * - Scan for special code units in the input. + * If our assumption was correct the __pos will be at the end of the input. + */ + const ptrdiff_t __length = __last - __first; + const _CharT* __limit = + __first + + (__precision == -1 ? __length : _VSTD::min(__length, __precision)); + ptrdiff_t __size = __limit - __first; + const _CharT* __pos = + __detail::__estimate_column_width_fast(__first, __limit); + + if (__pos == __limit) + return {__limit, __size, __size < __width}; + + /* + * Our assumption was wrong, there are special Unicode code units. + * The range [__first, __pos) contains a set of code units with the + * following property: + * Every _CharT in the range will be rendered in 1 column. + * + * If there's no maximum width and the parsed size already exceeds the + * minimum required width. The real size isn't important. So bail out. + */ + if (__precision == -1 && (__pos - __first) >= __width) + return {__last, 0, false}; + + /* If there's a __precision, truncate the output to that width. */ + ptrdiff_t __prefix = __pos - __first; + if (__precision != -1) { + _LIBCPP_ASSERT(__precision > __prefix, "Logic error."); + auto __lengh_info = __detail::__estimate_column_width( + __pos, __last, __precision - __prefix); + __size = __lengh_info.__width + __prefix; + return {__lengh_info.__ptr, __size, __size < __width}; + } + + /* Else use __width to determine the number of required padding characters. */ + _LIBCPP_ASSERT(__width > __prefix, "Logic error."); + /* + * The column width is always one or two columns. For the precision the wanted + * column width is the maximum, for the width it's the minimum. Using the + * width estimation with its truncating behavior will result in the wrong + * result in the following case: + * - The last code unit processed requires two columns and exceeds the + * maximum column width. + * By increasing the __maximum by one avoids this issue. (It means it may + * pass one code point more than required to determine the proper result; + * that however isn't a problem for the algorithm.) + */ + size_t __maximum = 1 + __width - __prefix; + auto __lengh_info = + __detail::__estimate_column_width(__pos, __last, __maximum); + if (__lengh_info.__ptr != __last) { + // Consumed the width number of code units. The exact size of the string + // is unknown. We only know we don't need to align the output. + _LIBCPP_ASSERT(static_cast(__lengh_info.__width + __prefix) >= + __width, + "Logic error"); + return {__last, 0, false}; + } + + __size = __lengh_info.__width + __prefix; + return {__last, __size, __size < __width}; +} +#else // _LIBCPP_HAS_NO_UNICODE +template +_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> +__get_string_alignment(const _CharT* __first, const _CharT* __last, + ptrdiff_t __width, ptrdiff_t __precision) noexcept { + const ptrdiff_t __length = __last - __first; + const _CharT* __limit = + __first + + (__precision == -1 ? __length : _VSTD::min(__length, __precision)); + ptrdiff_t __size = __limit - __first; + return {__limit, __size, __size < __width}; +} +#endif // _LIBCPP_HAS_NO_UNICODE + +} // namespace __format_spec + +# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H diff --git a/lib/libcxx/include/__function_like.h b/lib/libcxx/include/__function_like.h deleted file mode 100644 index 8a3597bacd..0000000000 --- a/lib/libcxx/include/__function_like.h +++ /dev/null @@ -1,56 +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___ITERATOR_FUNCTION_LIKE_H -#define _LIBCPP___ITERATOR_FUNCTION_LIKE_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 !defined(_LIBCPP_HAS_NO_RANGES) - -namespace ranges { -// Per [range.iter.ops.general] and [algorithms.requirements], functions in namespace std::ranges -// can't be found by ADL and inhibit ADL when found by unqualified lookup. The easiest way to -// facilitate this is to use function objects. -// -// Since these are still standard library functions, we use `__function_like` to eliminate most of -// the properties that function objects get by default (e.g. semiregularity, addressability), to -// limit the surface area of the unintended public interface, so as to curb the effect of Hyrum's -// law. -struct __function_like { - __function_like() = delete; - __function_like(__function_like const&) = delete; - __function_like& operator=(__function_like const&) = delete; - - void operator&() const = delete; - - struct __tag { }; - -protected: - constexpr explicit __function_like(__tag) noexcept {} - ~__function_like() = default; -}; -} // namespace ranges - -#endif // !defined(_LIBCPP_HAS_NO_RANGES) - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ITERATOR_FUNCTION_LIKE_H diff --git a/lib/libcxx/include/__functional/bind.h b/lib/libcxx/include/__functional/bind.h index 79dfad723c..11a51e5957 100644 --- a/lib/libcxx/include/__functional/bind.h +++ b/lib/libcxx/include/__functional/bind.h @@ -11,8 +11,8 @@ #define _LIBCPP___FUNCTIONAL_BIND_H #include <__config> -#include <__functional/weak_result_type.h> #include <__functional/invoke.h> +#include <__functional/weak_result_type.h> #include #include #include @@ -23,22 +23,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template struct __is_bind_expression : public false_type {}; -template struct _LIBCPP_TEMPLATE_VIS is_bind_expression - : public __is_bind_expression::type> {}; +template +struct is_bind_expression : _If< + _IsSame<_Tp, typename __uncvref<_Tp>::type>::value, + false_type, + is_bind_expression::type> +> {}; #if _LIBCPP_STD_VER > 14 template -_LIBCPP_INLINE_VAR constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; +inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; #endif -template struct __is_placeholder : public integral_constant {}; -template struct _LIBCPP_TEMPLATE_VIS is_placeholder - : public __is_placeholder::type> {}; +template +struct is_placeholder : _If< + _IsSame<_Tp, typename __uncvref<_Tp>::type>::value, + integral_constant, + is_placeholder::type> +> {}; #if _LIBCPP_STD_VER > 14 template -_LIBCPP_INLINE_VAR constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; +inline constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; #endif namespace placeholders @@ -58,22 +64,22 @@ _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 -/* _LIBCPP_INLINE_VAR */ constexpr __ph<1> _1{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<2> _2{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<3> _3{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<4> _4{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<5> _5{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<6> _6{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<7> _7{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<8> _8{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<9> _9{}; -/* _LIBCPP_INLINE_VAR */ constexpr __ph<10> _10{}; +/* 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) -} // placeholders +} // namespace placeholders template -struct __is_placeholder > +struct is_placeholder > : public integral_constant {}; @@ -97,7 +103,7 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) template inline _LIBCPP_INLINE_VISIBILITY -typename _EnableIf +typename __enable_if_t < is_bind_expression<_Ti>::value, __invoke_of<_Ti&, _Uj...> @@ -304,7 +310,7 @@ public: }; template -struct __is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; +struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; template class __bind_r @@ -359,7 +365,7 @@ public: }; template -struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; +struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 diff --git a/lib/libcxx/include/__functional/bind_back.h b/lib/libcxx/include/__functional/bind_back.h new file mode 100644 index 0000000000..a0089e1fb0 --- /dev/null +++ b/lib/libcxx/include/__functional/bind_back.h @@ -0,0 +1,65 @@ +// -*- 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___FUNCTIONAL_BIND_BACK_H +#define _LIBCPP___FUNCTIONAL_BIND_BACK_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.h> +#include <__utility/forward.h> +#include <__utility/integer_sequence.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 + +template > +struct __bind_back_op; + +template +struct __bind_back_op<_NBound, index_sequence<_Ip...>> { + template + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Fn&& __f, _Bound&& __bound, _Args&& ...__args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_Bound>(__bound))...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_Bound>(__bound))...)) + { return _VSTD::invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)..., _VSTD::get<_Ip>(_VSTD::forward<_Bound>(__bound))...); } +}; + +template +struct __bind_back_t : __perfect_forward<__bind_back_op>, _Fn, _BoundArgs> { + using __perfect_forward<__bind_back_op>, _Fn, _BoundArgs>::__perfect_forward; +}; + +template , _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible>... + >::value +>> +_LIBCPP_HIDE_FROM_ABI +constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) + noexcept(noexcept(__bind_back_t, tuple...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_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 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_BIND_BACK_H diff --git a/lib/libcxx/include/__functional/bind_front.h b/lib/libcxx/include/__functional/bind_front.h index 8690499f2b..31397ec540 100644 --- a/lib/libcxx/include/__functional/bind_front.h +++ b/lib/libcxx/include/__functional/bind_front.h @@ -11,8 +11,8 @@ #define _LIBCPP___FUNCTIONAL_BIND_FRONT_H #include <__config> -#include <__functional/perfect_forward.h> #include <__functional/invoke.h> +#include <__functional/perfect_forward.h> #include #include @@ -24,25 +24,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 -struct __bind_front_op -{ - template - constexpr static auto __call(_Args&&... __args) - noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) - -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) - { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +struct __bind_front_op { + template + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Args&& ...__args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } }; -template, _Fn>, - is_move_constructible>, - is_constructible, _Args>..., - is_move_constructible>... - >::value>> -constexpr auto bind_front(_Fn&& __f, _Args&&... __args) -{ - return __perfect_forward<__bind_front_op, _Fn, _Args...>(_VSTD::forward<_Fn>(__f), - _VSTD::forward<_Args>(__args)...); +template +struct __bind_front_t : __perfect_forward<__bind_front_op, _Fn, _BoundArgs...> { + using __perfect_forward<__bind_front_op, _Fn, _BoundArgs...>::__perfect_forward; +}; + +template , _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible>... + >::value +>> +_LIBCPP_HIDE_FROM_ABI +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 diff --git a/lib/libcxx/include/__functional/compose.h b/lib/libcxx/include/__functional/compose.h new file mode 100644 index 0000000000..d9d75875c2 --- /dev/null +++ b/lib/libcxx/include/__functional/compose.h @@ -0,0 +1,52 @@ +// -*- 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___FUNCTIONAL_COMPOSE_H +#define _LIBCPP___FUNCTIONAL_COMPOSE_H + +#include <__config> +#include <__functional/invoke.h> +#include <__functional/perfect_forward.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 > 17 + +struct __compose_op { + template + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Fn1&& __f1, _Fn2&& __f2, _Args&&... __args) const + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...)))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...))) + { return _VSTD::invoke(_VSTD::forward<_Fn1>(__f1), _VSTD::invoke(_VSTD::forward<_Fn2>(__f2), _VSTD::forward<_Args>(__args)...)); } +}; + +template +struct __compose_t : __perfect_forward<__compose_op, _Fn1, _Fn2> { + using __perfect_forward<__compose_op, _Fn1, _Fn2>::__perfect_forward; +}; + +template +_LIBCPP_HIDE_FROM_ABI +constexpr auto __compose(_Fn1&& __f1, _Fn2&& __f2) + noexcept(noexcept(__compose_t, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_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 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FUNCTIONAL_COMPOSE_H diff --git a/lib/libcxx/include/__functional/function.h b/lib/libcxx/include/__functional/function.h index ba629e1d14..6bb7eb7e8a 100644 --- a/lib/libcxx/include/__functional/function.h +++ b/lib/libcxx/include/__functional/function.h @@ -11,10 +11,12 @@ #define _LIBCPP___FUNCTIONAL_FUNCTION_H #include <__config> +#include <__debug> #include <__functional/binary_function.h> #include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> #include <__memory/shared_ptr.h> @@ -34,10 +36,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD class _LIBCPP_EXCEPTION_ABI bad_function_call : public exception { -#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION public: +// Note that when a key function is not used, every translation unit that uses +// bad_function_call will end up containing a weak definition of the vtable and +// typeinfo. +#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION virtual ~bad_function_call() _NOEXCEPT; +#else + virtual ~bad_function_call() _NOEXCEPT {} +#endif +#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE virtual const char* what() const _NOEXCEPT; #endif }; @@ -126,8 +135,8 @@ class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> __compressed_pair<_Fp, _Ap> __f_; public: - typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; - typedef _LIBCPP_NODEBUG_TYPE _Ap _Alloc; + typedef _LIBCPP_NODEBUG _Fp _Target; + typedef _LIBCPP_NODEBUG _Ap _Alloc; _LIBCPP_INLINE_VISIBILITY const _Target& __target() const { return __f_.first(); } @@ -204,7 +213,7 @@ class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { _Fp __f_; public: - typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; + typedef _LIBCPP_NODEBUG _Fp _Target; _LIBCPP_INLINE_VISIBILITY const _Target& __target() const { return __f_; } @@ -352,7 +361,7 @@ const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT { if (__ti == typeid(_Fp)) - return &__f_.__target(); + return _VSTD::addressof(__f_.__target()); return nullptr; } @@ -938,7 +947,7 @@ public: #endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC -} // __function +} // namespace __function template class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> @@ -1044,7 +1053,7 @@ public: #endif // _LIBCPP_NO_RTTI }; -#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +#if _LIBCPP_STD_VER >= 17 template function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; @@ -1089,7 +1098,7 @@ struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { usin template::type> function(_Fp) -> function<_Stripped>; -#endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES +#endif // _LIBCPP_STD_VER >= 17 template function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} @@ -1384,7 +1393,7 @@ const void* __func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const { if (__ti == typeid(_Fp)) - return &__f_.first(); + return _VSTD::addressof(__f_.first()); return (const void*)0; } @@ -1655,7 +1664,7 @@ __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const #endif // _LIBCPP_NO_RTTI -} // __function +} // namespace __function template class _LIBCPP_TEMPLATE_VIS function<_Rp()> @@ -1709,13 +1718,11 @@ public: // 20.7.16.2.3, function capacity: _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} -private: - // deleted overloads close possible hole in the type system template - bool operator==(const function<_R2()>&) const;// = delete; + bool operator==(const function<_R2()>&) const = delete; template - bool operator!=(const function<_R2()>&) const;// = delete; -public: + bool operator!=(const function<_R2()>&) const = delete; + // 20.7.16.2.4, function invocation: _Rp operator()() const; @@ -1989,13 +1996,11 @@ public: // 20.7.16.2.3, function capacity: _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} -private: - // deleted overloads close possible hole in the type system template - bool operator==(const function<_R2(_B0)>&) const;// = delete; + bool operator==(const function<_R2(_B0)>&) const = delete; template - bool operator!=(const function<_R2(_B0)>&) const;// = delete; -public: + bool operator!=(const function<_R2(_B0)>&) const = delete; + // 20.7.16.2.4, function invocation: _Rp operator()(_A0) const; @@ -2269,13 +2274,11 @@ public: // 20.7.16.2.3, function capacity: _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} -private: - // deleted overloads close possible hole in the type system template - bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete; + bool operator==(const function<_R2(_B0, _B1)>&) const = delete; template - bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete; -public: + bool operator!=(const function<_R2(_B0, _B1)>&) const = delete; + // 20.7.16.2.4, function invocation: _Rp operator()(_A0, _A1) const; @@ -2548,13 +2551,11 @@ public: // 20.7.16.2.3, function capacity: _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} -private: - // deleted overloads close possible hole in the type system template - bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; + bool operator==(const function<_R2(_B0, _B1, _B2)>&) const = delete; template - bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; -public: + bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const = delete; + // 20.7.16.2.4, function invocation: _Rp operator()(_A0, _A1, _A2) const; diff --git a/lib/libcxx/include/__functional/hash.h b/lib/libcxx/include/__functional/hash.h index ebcbbad133..de0c161f47 100644 --- a/lib/libcxx/include/__functional/hash.h +++ b/lib/libcxx/include/__functional/hash.h @@ -16,9 +16,9 @@ #include <__utility/move.h> #include <__utility/pair.h> #include <__utility/swap.h> +#include #include #include -#include #include #include @@ -26,9 +26,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -564,6 +561,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP #endif // _LIBCPP_HAS_NO_UNICODE_CHARS +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> struct _LIBCPP_TEMPLATE_VIS hash @@ -579,6 +577,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_INLINE_VISIBILITY size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast(__v);} }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> @@ -839,35 +838,33 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP #ifndef _LIBCPP_CXX03_LANG template -using __check_hash_requirements _LIBCPP_NODEBUG_TYPE = integral_constant::value && is_move_constructible<_Hash>::value && __invokable_r::value >; template > -using __has_enabled_hash _LIBCPP_NODEBUG_TYPE = integral_constant::value && is_default_constructible<_Hash>::value >; #if _LIBCPP_STD_VER > 14 template -using __enable_hash_helper_imp _LIBCPP_NODEBUG_TYPE = _Type; +using __enable_hash_helper_imp _LIBCPP_NODEBUG = _Type; template -using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = __enable_hash_helper_imp<_Type, +using __enable_hash_helper _LIBCPP_NODEBUG = __enable_hash_helper_imp<_Type, typename enable_if<__all<__has_enabled_hash<_Keys>::value...>::value>::type >; #else template -using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = _Type; +using __enable_hash_helper _LIBCPP_NODEBUG = _Type; #endif #endif // !_LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FUNCTIONAL_HASH_H diff --git a/lib/libcxx/include/__functional/mem_fn.h b/lib/libcxx/include/__functional/mem_fn.h index 1fa070a42c..0ec8423343 100644 --- a/lib/libcxx/include/__functional/mem_fn.h +++ b/lib/libcxx/include/__functional/mem_fn.h @@ -11,9 +11,9 @@ #define _LIBCPP___FUNCTIONAL_MEM_FN_H #include <__config> -#include <__functional/weak_result_type.h> #include <__functional/binary_function.h> #include <__functional/invoke.h> +#include <__functional/weak_result_type.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/lib/libcxx/include/__functional/mem_fun_ref.h b/lib/libcxx/include/__functional/mem_fun_ref.h index 4616da0b07..830936c1b0 100644 --- a/lib/libcxx/include/__functional/mem_fun_ref.h +++ b/lib/libcxx/include/__functional/mem_fun_ref.h @@ -11,8 +11,8 @@ #define _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H #include <__config> -#include <__functional/unary_function.h> #include <__functional/binary_function.h> +#include <__functional/unary_function.h> #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 632be5ff09..36aab2eb79 100644 --- a/lib/libcxx/include/__functional/not_fn.h +++ b/lib/libcxx/include/__functional/not_fn.h @@ -11,8 +11,8 @@ #define _LIBCPP___FUNCTIONAL_NOT_FN_H #include <__config> -#include <__functional/perfect_forward.h> #include <__functional/invoke.h> +#include <__functional/perfect_forward.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,21 +23,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -struct __not_fn_op -{ - template - static _LIBCPP_CONSTEXPR_AFTER_CXX17 auto __call(_Args&&... __args) - noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) - -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) - { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +struct __not_fn_op { + template + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_AFTER_CXX17 auto operator()(_Args&&... __args) const + noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } }; -template, _Fn> && - is_move_constructible_v<_Fn>>> -_LIBCPP_CONSTEXPR_AFTER_CXX17 auto not_fn(_Fn&& __f) -{ - return __perfect_forward<__not_fn_op, _Fn>(_VSTD::forward<_Fn>(__f)); +template +struct __not_fn_t : __perfect_forward<__not_fn_op, _Fn> { + using __perfect_forward<__not_fn_op, _Fn>::__perfect_forward; +}; + +template , _Fn> && + is_move_constructible_v> +>> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto not_fn(_Fn&& __f) { + return __not_fn_t>(_VSTD::forward<_Fn>(__f)); } #endif // _LIBCPP_STD_VER > 14 diff --git a/lib/libcxx/include/__functional/operations.h b/lib/libcxx/include/__functional/operations.h index 667d17988b..0c7c6d4fcf 100644 --- a/lib/libcxx/include/__functional/operations.h +++ b/lib/libcxx/include/__functional/operations.h @@ -53,9 +53,9 @@ struct _LIBCPP_TEMPLATE_VIS plus template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -90,9 +90,9 @@ struct _LIBCPP_TEMPLATE_VIS minus template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -127,9 +127,9 @@ struct _LIBCPP_TEMPLATE_VIS multiplies template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -164,9 +164,9 @@ struct _LIBCPP_TEMPLATE_VIS divides template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -201,9 +201,9 @@ struct _LIBCPP_TEMPLATE_VIS modulus template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -237,9 +237,9 @@ struct _LIBCPP_TEMPLATE_VIS negate template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_Tp&& __x) const - _NOEXCEPT_(noexcept(- _VSTD::forward<_Tp>(__x))) - -> decltype (- _VSTD::forward<_Tp>(__x)) - { return - _VSTD::forward<_Tp>(__x); } + noexcept(noexcept(- _VSTD::forward<_Tp>(__x))) + -> decltype( - _VSTD::forward<_Tp>(__x)) + { return - _VSTD::forward<_Tp>(__x); } typedef void is_transparent; }; #endif @@ -276,9 +276,9 @@ struct _LIBCPP_TEMPLATE_VIS bit_and template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -307,9 +307,9 @@ struct _LIBCPP_TEMPLATE_VIS bit_not template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_Tp&& __x) const - _NOEXCEPT_(noexcept(~_VSTD::forward<_Tp>(__x))) - -> decltype (~_VSTD::forward<_Tp>(__x)) - { return ~_VSTD::forward<_Tp>(__x); } + noexcept(noexcept(~_VSTD::forward<_Tp>(__x))) + -> decltype( ~_VSTD::forward<_Tp>(__x)) + { return ~_VSTD::forward<_Tp>(__x); } typedef void is_transparent; }; #endif @@ -344,9 +344,9 @@ struct _LIBCPP_TEMPLATE_VIS bit_or template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -381,9 +381,9 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -420,9 +420,9 @@ struct _LIBCPP_TEMPLATE_VIS equal_to template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -457,9 +457,9 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -494,9 +494,9 @@ struct _LIBCPP_TEMPLATE_VIS less template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -531,9 +531,9 @@ struct _LIBCPP_TEMPLATE_VIS less_equal template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -568,9 +568,9 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -605,9 +605,9 @@ struct _LIBCPP_TEMPLATE_VIS greater template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -644,9 +644,9 @@ struct _LIBCPP_TEMPLATE_VIS logical_and template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif @@ -680,9 +680,9 @@ struct _LIBCPP_TEMPLATE_VIS logical_not template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_Tp&& __x) const - _NOEXCEPT_(noexcept(!_VSTD::forward<_Tp>(__x))) - -> decltype (!_VSTD::forward<_Tp>(__x)) - { return !_VSTD::forward<_Tp>(__x); } + noexcept(noexcept(!_VSTD::forward<_Tp>(__x))) + -> decltype( !_VSTD::forward<_Tp>(__x)) + { return !_VSTD::forward<_Tp>(__x); } typedef void is_transparent; }; #endif @@ -717,9 +717,9 @@ struct _LIBCPP_TEMPLATE_VIS logical_or template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const - _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u))) - -> decltype (_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u)) - { return _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u); } + noexcept(noexcept(_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u))) + -> decltype( _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif diff --git a/lib/libcxx/include/__functional/perfect_forward.h b/lib/libcxx/include/__functional/perfect_forward.h index a5678e1593..308b304a76 100644 --- a/lib/libcxx/include/__functional/perfect_forward.h +++ b/lib/libcxx/include/__functional/perfect_forward.h @@ -11,9 +11,11 @@ #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H #include <__config> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -23,63 +25,68 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -template::value>::type> +template struct __perfect_forward_impl; -template -struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>> -{ +template +struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _Bound...> { +private: tuple<_Bound...> __bound_; - template - _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) & - noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))) - -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)) - {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);} +public: + template , _BoundArgs&&...> + >> + explicit constexpr __perfect_forward_impl(_BoundArgs&& ...__bound) + : __bound_(_VSTD::forward<_BoundArgs>(__bound)...) + { } - template - _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const& - noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))) - -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)) - {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);} + __perfect_forward_impl(__perfect_forward_impl const&) = default; + __perfect_forward_impl(__perfect_forward_impl&&) = default; - template - _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) && - noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...))) - -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...)) - {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...);} + __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; + __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; - template - _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&& - noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...))) - -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...)) - {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., - _VSTD::forward<_Args>(__args)...);} + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...); } - template>::type, - class = _EnableIf>> - constexpr __perfect_forward_impl(__perfect_forward_impl const& __other) - : __bound_(__other.__bound_) {} + template >> + auto operator()(_Args&&...) & = delete; - template>::type, - class = _EnableIf>> - constexpr __perfect_forward_impl(__perfect_forward_impl && __other) - : __bound_(_VSTD::move(__other.__bound_)) {} + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const& + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(__bound_)..., _VSTD::forward<_Args>(__args)...); } - template - explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) : - __bound_(_VSTD::forward<_BoundArgs>(__bound)...) { } + template >> + auto operator()(_Args&&...) const& = delete; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) && + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) && = delete; + + template >> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&& + noexcept(noexcept(_Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...)) + { return _Op()(_VSTD::get<_Idx>(_VSTD::move(__bound_))..., _VSTD::forward<_Args>(__args)...); } + + template >> + auto operator()(_Args&&...) const&& = delete; }; -template -using __perfect_forward = - __perfect_forward_impl<_Op, __tuple_types...>>; +// __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require]. +template +using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; #endif // _LIBCPP_STD_VER > 14 diff --git a/lib/libcxx/include/__functional/ranges_operations.h b/lib/libcxx/include/__functional/ranges_operations.h index 777c535251..a0ea7ccaff 100644 --- a/lib/libcxx/include/__functional/ranges_operations.h +++ b/lib/libcxx/include/__functional/ranges_operations.h @@ -20,7 +20,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + namespace ranges { struct equal_to { @@ -90,7 +91,7 @@ struct greater_equal { }; } // namespace ranges -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/reference_wrapper.h b/lib/libcxx/include/__functional/reference_wrapper.h index 09f4a64945..d04d51568b 100644 --- a/lib/libcxx/include/__functional/reference_wrapper.h +++ b/lib/libcxx/include/__functional/reference_wrapper.h @@ -34,25 +34,16 @@ public: private: type* __f_; -#ifndef _LIBCPP_CXX03_LANG static void __fun(_Tp&) _NOEXCEPT; static void __fun(_Tp&&) = delete; -#endif public: - // construct/copy/destroy -#ifdef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY - reference_wrapper(type& __f) _NOEXCEPT - : __f_(_VSTD::addressof(__f)) {} -#else - template ::value, decltype(__fun(declval<_Up>())) >> + template ::value, decltype(__fun(declval<_Up>())) > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(declval<_Up>()))) { type& __f = static_cast<_Up&&>(__u); __f_ = _VSTD::addressof(__f); } -#endif // access _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -176,7 +167,7 @@ public: #endif // _LIBCPP_CXX03_LANG }; -#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +#if _LIBCPP_STD_VER > 14 template reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; #endif @@ -194,7 +185,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) _NOEXCEPT { - return _VSTD::ref(__t.get()); + return __t; } template @@ -210,13 +201,11 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper cref(reference_wrapper<_Tp> __t) _NOEXCEPT { - return _VSTD::cref(__t.get()); + return __t; } -#ifndef _LIBCPP_CXX03_LANG template void ref(const _Tp&&) = delete; template void cref(const _Tp&&) = delete; -#endif _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__functional/unary_function.h b/lib/libcxx/include/__functional/unary_function.h index 8084ef4b03..499f996467 100644 --- a/lib/libcxx/include/__functional/unary_function.h +++ b/lib/libcxx/include/__functional/unary_function.h @@ -15,9 +15,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -29,6 +26,4 @@ struct _LIBCPP_TEMPLATE_VIS unary_function _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H diff --git a/lib/libcxx/include/__functional/unwrap_ref.h b/lib/libcxx/include/__functional/unwrap_ref.h index 4d091ec35c..dc309add90 100644 --- a/lib/libcxx/include/__functional/unwrap_ref.h +++ b/lib/libcxx/include/__functional/unwrap_ref.h @@ -15,19 +15,16 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template -struct __unwrap_reference { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; +struct __unwrap_reference { typedef _LIBCPP_NODEBUG _Tp type; }; template class reference_wrapper; template -struct __unwrap_reference > { typedef _LIBCPP_NODEBUG_TYPE _Tp& type; }; +struct __unwrap_reference > { typedef _LIBCPP_NODEBUG _Tp& type; }; template struct decay; @@ -57,6 +54,4 @@ struct __unwrap_ref_decay _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FUNCTIONAL_UNWRAP_REF_H diff --git a/lib/libcxx/include/__functional/weak_result_type.h b/lib/libcxx/include/__functional/weak_result_type.h index 2ee85acf1e..32b1e0b1c6 100644 --- a/lib/libcxx/include/__functional/weak_result_type.h +++ b/lib/libcxx/include/__functional/weak_result_type.h @@ -89,7 +89,7 @@ struct __weak_result_type_imp // bool is true : public __maybe_derive_from_unary_function<_Tp>, public __maybe_derive_from_binary_function<_Tp> { - typedef _LIBCPP_NODEBUG_TYPE typename _Tp::result_type result_type; + typedef _LIBCPP_NODEBUG typename _Tp::result_type result_type; }; template @@ -110,19 +110,19 @@ struct __weak_result_type template struct __weak_result_type<_Rp ()> { - typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; + typedef _LIBCPP_NODEBUG _Rp result_type; }; template struct __weak_result_type<_Rp (&)()> { - typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; + typedef _LIBCPP_NODEBUG _Rp result_type; }; template struct __weak_result_type<_Rp (*)()> { - typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; + typedef _LIBCPP_NODEBUG _Rp result_type; }; // 1 argument case diff --git a/lib/libcxx/include/__hash_table b/lib/libcxx/include/__hash_table index df0f7c80db..adc732cffb 100644 --- a/lib/libcxx/include/__hash_table +++ b/lib/libcxx/include/__hash_table @@ -288,9 +288,7 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) { -#if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__insert_i(this); -#endif + _VSTD::__debug_db_insert_i(this); } #if _LIBCPP_DEBUG_LEVEL == 2 @@ -298,7 +296,7 @@ public: __hash_iterator(const __hash_iterator& __i) : __node_(__i.__node_) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); } _LIBCPP_INLINE_VISIBILITY @@ -310,9 +308,9 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator=(const __hash_iterator& __i) { - if (this != &__i) + if (this != _VSTD::addressof(__i)) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); __node_ = __i.__node_; } return *this; @@ -400,9 +398,7 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) { -#if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__insert_i(this); -#endif + _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY @@ -410,7 +406,7 @@ public: : __node_(__x.__node_) { #if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__iterator_copy(this, &__x); + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); #endif } @@ -419,7 +415,7 @@ public: __hash_const_iterator(const __hash_const_iterator& __i) : __node_(__i.__node_) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); } _LIBCPP_INLINE_VISIBILITY @@ -431,9 +427,9 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator=(const __hash_const_iterator& __i) { - if (this != &__i) + if (this != _VSTD::addressof(__i)) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); __node_ = __i.__node_; } return *this; @@ -517,9 +513,7 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) { -#if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__insert_i(this); -#endif + _VSTD::__debug_db_insert_i(this); } #if _LIBCPP_DEBUG_LEVEL == 2 @@ -529,7 +523,7 @@ public: __bucket_(__i.__bucket_), __bucket_count_(__i.__bucket_count_) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); } _LIBCPP_INLINE_VISIBILITY @@ -541,9 +535,9 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator=(const __hash_local_iterator& __i) { - if (this != &__i) + if (this != _VSTD::addressof(__i)) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); __node_ = __i.__node_; __bucket_ = __i.__bucket_; __bucket_count_ = __i.__bucket_count_; @@ -651,9 +645,7 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) { -#if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__insert_i(this); -#endif + _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY @@ -663,7 +655,7 @@ public: __bucket_count_(__x.__bucket_count_) { #if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__iterator_copy(this, &__x); + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); #endif } @@ -674,7 +666,7 @@ public: __bucket_(__i.__bucket_), __bucket_count_(__i.__bucket_count_) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); } _LIBCPP_INLINE_VISIBILITY @@ -686,9 +678,9 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) { - if (this != &__i) + if (this != _VSTD::addressof(__i)) { - __get_db()->__iterator_copy(this, &__i); + __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); __node_ = __i.__node_; __bucket_ = __i.__bucket_; __bucket_count_ = __i.__bucket_count_; @@ -1541,7 +1533,7 @@ template __hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) { - if (this != &__u) + if (this != _VSTD::addressof(__u)) { __copy_assign_alloc(__u); hash_function() = __u.hash_function(); @@ -1623,7 +1615,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __u.size() = 0; } #if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->swap(this, &__u); + __get_db()->swap(this, _VSTD::addressof(__u)); #endif } @@ -2029,11 +2021,9 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( const_iterator __p, __node_pointer __cp) { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); -#endif + _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_; @@ -2158,11 +2148,9 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( const_iterator __p, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); -#endif + _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(); @@ -2348,7 +2336,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc) size_type __chash = __constrain_hash(__cp->__hash(), __nbc); __bucket_list_[__chash] = __pp; size_type __phash = __chash; - for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr; + for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) { __chash = __constrain_hash(__cp->__hash(), __nbc); @@ -2484,12 +2472,12 @@ 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_DEBUG_ASSERT(__p != end(), + "unordered container erase(iterator) called with a non-dereferenceable iterator"); #if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__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); #else iterator __r(__np); @@ -2504,14 +2492,12 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); -#endif + _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; @@ -2741,7 +2727,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = __u.__p1_.first().__ptr(); #if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->swap(this, &__u); + __get_db()->swap(this, _VSTD::addressof(__u)); #endif } @@ -2758,7 +2744,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const { for (__np = __np->__next_; __np != nullptr && __constrain_hash(__np->__hash(), __bc) == __n; - __np = __np->__next_, ++__r) + __np = __np->__next_, (void) ++__r) ; } return __r; diff --git a/lib/libcxx/include/__iterator/access.h b/lib/libcxx/include/__iterator/access.h index c0576b4590..5e0d6b3515 100644 --- a/lib/libcxx/include/__iterator/access.h +++ b/lib/libcxx/include/__iterator/access.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -129,6 +126,4 @@ end(const _Cp& __c) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_ACCESS_H diff --git a/lib/libcxx/include/__iterator/advance.h b/lib/libcxx/include/__iterator/advance.h index 47bce1ddfb..d74d6b8b92 100644 --- a/lib/libcxx/include/__iterator/advance.h +++ b/lib/libcxx/include/__iterator/advance.h @@ -12,13 +12,12 @@ #include <__config> #include <__debug> -#include <__function_like.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__utility/move.h> -#include #include +#include #include #include @@ -26,9 +25,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -58,7 +54,7 @@ void __advance(_RandIter& __i, typename iterator_traits<_RandIter>::difference_t template < class _InputIter, class _Distance, class _IntegralDistance = decltype(_VSTD::__convert_to_integral(declval<_Distance>())), - class = _EnableIf::value> > + class = __enable_if_t::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 void advance(_InputIter& __i, _Distance __orig_n) { typedef typename iterator_traits<_InputIter>::difference_type _Difference; @@ -68,18 +64,15 @@ void advance(_InputIter& __i, _Distance __orig_n) { _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); } -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +// [range.iter.op.advance] namespace ranges { -// [range.iter.op.advance] -struct __advance_fn final : private __function_like { -private: - template - _LIBCPP_HIDE_FROM_ABI - static constexpr _Tp __magnitude_geq(_Tp __a, _Tp __b) noexcept { - return __a < 0 ? (__a <= __b) : (__a >= __b); - } +namespace __advance { +struct __fn { +private: template _LIBCPP_HIDE_FROM_ABI static constexpr void __advance_forward(_Ip& __i, iter_difference_t<_Ip> __n) { @@ -99,8 +92,6 @@ private: } public: - constexpr explicit __advance_fn(__tag __x) noexcept : __function_like(__x) {} - // Preconditions: If `I` does not model `bidirectional_iterator`, `n` is not negative. template _LIBCPP_HIDE_FROM_ABI @@ -158,6 +149,12 @@ public: // If `S` and `I` model `sized_sentinel_for`: if constexpr (sized_sentinel_for<_Sp, _Ip>) { // If |n| >= |bound - i|, equivalent to `ranges::advance(i, bound)`. + // __magnitude_geq(a, b) returns |a| >= |b|, assuming they have the same sign. + auto __magnitude_geq = [](auto __a, auto __b) { + return __a == 0 ? __b == 0 : + __a > 0 ? __a >= __b : + __a <= __b; + }; if (const auto __M = __bound - __i; __magnitude_geq(__n, __M)) { (*this)(__i, __bound); return __n - __M; @@ -188,13 +185,15 @@ public: } }; -inline constexpr auto advance = __advance_fn(__function_like::__tag()); +} // namespace __advance + +inline namespace __cpo { + inline constexpr auto advance = __advance::__fn{}; +} // namespace __cpo } // namespace ranges -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _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 f34cb863bc..844babe5c5 100644 --- a/lib/libcxx/include/__iterator/back_insert_iterator.h +++ b/lib/libcxx/include/__iterator/back_insert_iterator.h @@ -21,9 +21,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -48,20 +45,20 @@ public: typedef void reference; typedef _Container container_type; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(const typename _Container::value_type& __value_) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(const typename _Container::value_type& __value_) {container->push_back(__value_); return *this;} #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(typename _Container::value_type&& __value_) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(typename _Container::value_type&& __value_) {container->push_back(_VSTD::move(__value_)); return *this;} #endif // _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator*() {return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator++() {return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator operator++(int) {return *this;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator*() {return *this;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator++() {return *this;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator operator++(int) {return *this;} }; template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator<_Container> back_inserter(_Container& __x) { @@ -70,6 +67,4 @@ 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/common_iterator.h b/lib/libcxx/include/__iterator/common_iterator.h index fb01d8bd4b..68309ee08b 100644 --- a/lib/libcxx/include/__iterator/common_iterator.h +++ b/lib/libcxx/include/__iterator/common_iterator.h @@ -25,12 +25,14 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +concept __can_use_postfix_proxy = + constructible_from, iter_reference_t<_Iter>> && + move_constructible>; template _Sent> requires (!same_as<_Iter, _Sent> && copyable<_Iter>) @@ -44,7 +46,7 @@ class common_iterator { : __value(_VSTD::move(__x)) {} public: - const iter_value_t<_Iter>* operator->() const { + constexpr const iter_value_t<_Iter>* operator->() const noexcept { return _VSTD::addressof(__value); } }; @@ -57,11 +59,7 @@ class common_iterator { : __value(_VSTD::forward>(__x)) {} public: - constexpr static bool __valid_for_iter = - constructible_from, iter_reference_t<_Iter>> && - move_constructible>; - - const iter_value_t<_Iter>& operator*() const { + constexpr const iter_value_t<_Iter>& operator*() const noexcept { return __value; } }; @@ -78,7 +76,7 @@ public: requires convertible_to && convertible_to constexpr common_iterator(const common_iterator<_I2, _S2>& __other) : __hold_([&]() -> variant<_Iter, _Sent> { - _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Constructed from valueless iterator."); + _LIBCPP_ASSERT(!__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_)}; @@ -88,7 +86,7 @@ public: 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(), "Assigned from valueless iterator."); + _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator"); auto __idx = __hold_.index(); auto __other_idx = __other.__hold_.index(); @@ -108,18 +106,16 @@ public: return *this; } - decltype(auto) operator*() + constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), - "Cannot dereference sentinel. Common iterator not holding an iterator."); + _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } - decltype(auto) operator*() const + constexpr decltype(auto) operator*() const requires __dereferenceable { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), - "Cannot dereference sentinel. Common iterator not holding an iterator."); + _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } @@ -130,9 +126,7 @@ public: is_reference_v> || constructible_from, iter_reference_t<_I2>>) { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), - "Cannot dereference sentinel. Common iterator not holding an iterator."); - + _LIBCPP_ASSERT(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>) { @@ -144,21 +138,18 @@ public: } common_iterator& operator++() { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), - "Cannot increment sentinel. Common iterator not holding an iterator."); + _LIBCPP_ASSERT(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(holds_alternative<_Iter>(__hold_), - "Cannot increment sentinel. Common iterator not holding an iterator."); - + _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); if constexpr (forward_iterator<_Iter>) { auto __tmp = *this; ++*this; return __tmp; } else if constexpr (requires (_Iter& __i) { { *__i++ } -> __referenceable; } || - !__postfix_proxy::__valid_for_iter) { + !__can_use_postfix_proxy<_Iter>) { return _VSTD::__unchecked_get<_Iter>(__hold_)++; } else { __postfix_proxy __p(**this); @@ -169,10 +160,9 @@ public: template _S2> requires sentinel_for<_Sent, _I2> - friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && - !__y.__hold_.valueless_by_exception(), - "One or both common_iterators are valueless. (Cannot compare valueless iterators.)"); + 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"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -188,10 +178,9 @@ public: template _S2> requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> - friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && - !__y.__hold_.valueless_by_exception(), - "One or both common_iterators are valueless. (Cannot compare valueless iterators.)"); + 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"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -210,10 +199,9 @@ public: template _I2, sized_sentinel_for<_Iter> _S2> requires sized_sentinel_for<_Sent, _I2> - friend iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && - !__y.__hold_.valueless_by_exception(), - "One or both common_iterators are valueless. (Cannot subtract valueless iterators.)"); + 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"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -230,24 +218,21 @@ public: return _VSTD::__unchecked_get<_Sent>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_); } - friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) + friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) noexcept(noexcept(ranges::iter_move(declval()))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), - "Cannot iter_move a sentinel. Common iterator not holding an iterator."); + _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); } template _I2, class _S2> - friend void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) + friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) noexcept(noexcept(ranges::iter_swap(declval(), declval()))) { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), - "Cannot swap __y with a sentinel. Common iterator (__x) not holding an iterator."); - _LIBCPP_ASSERT(holds_alternative<_Iter>(__y.__hold_), - "Cannot swap __x with a sentinel. Common iterator (__y) not holding an iterator."); - return ranges::iter_swap( _VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_Iter>(__y.__hold_)); + _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(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,10 +259,10 @@ struct __arrow_type_or_void { template requires __common_iter_has_ptr_op<_Iter, _Sent> struct __arrow_type_or_void<_Iter, _Sent> { - using type = decltype(declval>().operator->()); + using type = decltype(declval&>().operator->()); }; -template +template struct iterator_traits> { using iterator_concept = _If, forward_iterator_tag, @@ -291,11 +276,8 @@ struct iterator_traits> { using reference = iter_reference_t<_Iter>; }; - -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _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 6eb4aef105..f6d092c75d 100644 --- a/lib/libcxx/include/__iterator/concepts.h +++ b/lib/libcxx/include/__iterator/concepts.h @@ -24,14 +24,9 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) - -// clang-format off +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) // [iterator.concept.readable] template @@ -72,6 +67,8 @@ concept __signed_integer_like = signed_integral<_Tp>; template concept weakly_incrementable = + // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173). + !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly. movable<_Ip> && requires(_Ip __i) { typename iter_difference_t<_Ip>; @@ -172,7 +169,6 @@ concept contiguous_iterator = derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && is_lvalue_reference_v> && same_as, remove_cvref_t>> && - (is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) && requires(const _Ip& __i) { { _VSTD::to_address(__i) } -> same_as>>; }; @@ -261,12 +257,8 @@ concept indirectly_movable_storable = // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle // (both iter_swap and indirectly_swappable require indirectly_readable). -// clang-format on - -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_CONCEPTS_H diff --git a/lib/libcxx/include/__iterator/counted_iterator.h b/lib/libcxx/include/__iterator/counted_iterator.h index 7136aaf025..aaab3ac777 100644 --- a/lib/libcxx/include/__iterator/counted_iterator.h +++ b/lib/libcxx/include/__iterator/counted_iterator.h @@ -13,12 +13,14 @@ #include <__debug> #include <__iterator/concepts.h> #include <__iterator/default_sentinel.h> +#include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> -#include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> #include <__memory/pointer_traits.h> +#include <__utility/move.h> +#include #include #include @@ -26,12 +28,9 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) template struct __counted_iterator_concept {}; @@ -97,7 +96,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr const _Iter& base() const& { return __current_; } + constexpr const _Iter& base() const& noexcept { return __current_; } _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return _VSTD::move(__current_); } @@ -297,10 +296,8 @@ struct iterator_traits> : iterator_traits<_Iter> { add_pointer_t>, void>; }; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_COUNTED_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/data.h b/lib/libcxx/include/__iterator/data.h index cd8e37b96b..5e4946cc10 100644 --- a/lib/libcxx/include/__iterator/data.h +++ b/lib/libcxx/include/__iterator/data.h @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 @@ -51,6 +48,4 @@ constexpr const _Ep* data(initializer_list<_Ep> __il) noexcept { return __il.beg _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_DATA_H diff --git a/lib/libcxx/include/__iterator/default_sentinel.h b/lib/libcxx/include/__iterator/default_sentinel.h index 934a56fd9e..e12a5909cc 100644 --- a/lib/libcxx/include/__iterator/default_sentinel.h +++ b/lib/libcxx/include/__iterator/default_sentinel.h @@ -16,20 +16,15 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) struct default_sentinel_t { }; inline constexpr default_sentinel_t default_sentinel{}; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H diff --git a/lib/libcxx/include/__iterator/distance.h b/lib/libcxx/include/__iterator/distance.h index 33e4af84d3..50ed76a4e5 100644 --- a/lib/libcxx/include/__iterator/distance.h +++ b/lib/libcxx/include/__iterator/distance.h @@ -11,15 +11,18 @@ #define _LIBCPP___ITERATOR_DISTANCE_H #include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/size.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 @@ -49,8 +52,56 @@ distance(_InputIter __first, _InputIter __last) return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); } +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +// [range.iter.op.distance] + +namespace ranges { +namespace __distance { + +struct __fn { + template _Sp> + requires (!sized_sentinel_for<_Sp, _Ip>) + _LIBCPP_HIDE_FROM_ABI + constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const { + iter_difference_t<_Ip> __n = 0; + while (__first != __last) { + ++__first; + ++__n; + } + return __n; + } + + template> _Sp> + _LIBCPP_HIDE_FROM_ABI + constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const { + if constexpr (sized_sentinel_for<_Sp, __uncvref_t<_Ip>>) { + return __last - __first; + } else { + return __last - decay_t<_Ip>(__first); + } + } + + template + _LIBCPP_HIDE_FROM_ABI + constexpr range_difference_t<_Rp> operator()(_Rp&& __r) const { + if constexpr (sized_range<_Rp>) { + return static_cast>(ranges::size(__r)); + } else { + return operator()(ranges::begin(__r), ranges::end(__r)); + } + } +}; + +} // namespace __distance + +inline namespace __cpo { + inline constexpr auto distance = __distance::__fn{}; +} // namespace __cpo +} // namespace ranges + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_DISTANCE_H diff --git a/lib/libcxx/include/__iterator/empty.h b/lib/libcxx/include/__iterator/empty.h index 4dd59f5ccc..39cd560a27 100644 --- a/lib/libcxx/include/__iterator/empty.h +++ b/lib/libcxx/include/__iterator/empty.h @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 @@ -44,6 +41,4 @@ constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() = _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_EMPTY_H diff --git a/lib/libcxx/include/__iterator/erase_if_container.h b/lib/libcxx/include/__iterator/erase_if_container.h index a5dfd07205..08f6e22482 100644 --- a/lib/libcxx/include/__iterator/erase_if_container.h +++ b/lib/libcxx/include/__iterator/erase_if_container.h @@ -16,9 +16,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -40,6 +37,4 @@ __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 0421dd5c4b..b229a99f11 100644 --- a/lib/libcxx/include/__iterator/front_insert_iterator.h +++ b/lib/libcxx/include/__iterator/front_insert_iterator.h @@ -21,9 +21,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -70,6 +67,4 @@ 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 5a433982ba..3b68acc9bc 100644 --- a/lib/libcxx/include/__iterator/incrementable_traits.h +++ b/lib/libcxx/include/__iterator/incrementable_traits.h @@ -18,12 +18,9 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) // [incrementable.traits] template struct incrementable_traits {}; @@ -68,10 +65,8 @@ using iter_difference_t = typename conditional_t<__is_primary_template >, iterator_traits > >::difference_type; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H diff --git a/lib/libcxx/include/__iterator/indirectly_comparable.h b/lib/libcxx/include/__iterator/indirectly_comparable.h new file mode 100644 index 0000000000..ad5ff1a866 --- /dev/null +++ b/lib/libcxx/include/__iterator/indirectly_comparable.h @@ -0,0 +1,30 @@ +// -*- 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_INDIRECTLY_COMPARABLE_H +#define _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H + +#include <__config> +#include <__functional/identity.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +template +concept indirectly_comparable = + indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H diff --git a/lib/libcxx/include/__iterator/insert_iterator.h b/lib/libcxx/include/__iterator/insert_iterator.h index 2658141824..dc617c1c93 100644 --- a/lib/libcxx/include/__iterator/insert_iterator.h +++ b/lib/libcxx/include/__iterator/insert_iterator.h @@ -14,6 +14,7 @@ #include <__iterator/iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> +#include <__ranges/access.h> #include <__utility/move.h> #include @@ -21,11 +22,16 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +template +using __insert_iterator_iter_t = ranges::iterator_t<_Container>; +#else +template +using __insert_iterator_iter_t = typename _Container::iterator; +#endif + _LIBCPP_SUPPRESS_DEPRECATED_PUSH template class _LIBCPP_TEMPLATE_VIS insert_iterator @@ -36,7 +42,7 @@ class _LIBCPP_TEMPLATE_VIS insert_iterator _LIBCPP_SUPPRESS_DEPRECATED_POP protected: _Container* container; - typename _Container::iterator iter; // FIXME: `ranges::iterator_t` in C++20 mode + __insert_iterator_iter_t<_Container> iter; public: typedef output_iterator_tag iterator_category; typedef void value_type; @@ -49,7 +55,7 @@ public: typedef void reference; typedef _Container container_type; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, typename _Container::iterator __i) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, __insert_iterator_iter_t<_Container> __i) : container(_VSTD::addressof(__x)), iter(__i) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator=(const typename _Container::value_type& __value_) {iter = container->insert(iter, __value_); ++iter; return *this;} @@ -65,13 +71,11 @@ public: template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator<_Container> -inserter(_Container& __x, typename _Container::iterator __i) +inserter(_Container& __x, __insert_iterator_iter_t<_Container> __i) { return insert_iterator<_Container>(__x, __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 f39faa6d59..979d714edf 100644 --- a/lib/libcxx/include/__iterator/istream_iterator.h +++ b/lib/libcxx/include/__iterator/istream_iterator.h @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -70,12 +67,6 @@ public: bool operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); - - template - friend _LIBCPP_INLINE_VISIBILITY - bool - operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, - const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); }; template @@ -98,6 +89,4 @@ operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/istreambuf_iterator.h b/lib/libcxx/include/__iterator/istreambuf_iterator.h index 119698d54c..0c7676f169 100644 --- a/lib/libcxx/include/__iterator/istreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/istreambuf_iterator.h @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -105,6 +102,4 @@ bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a, _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/iter_move.h b/lib/libcxx/include/__iterator/iter_move.h index 5540799e19..45d9ade682 100644 --- a/lib/libcxx/include/__iterator/iter_move.h +++ b/lib/libcxx/include/__iterator/iter_move.h @@ -21,20 +21,23 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [iterator.cust.move] + +namespace ranges { +namespace __iter_move { -namespace ranges::__iter_move { void iter_move(); -template -concept __unqualified_iter_move = requires(_Ip&& __i) { - iter_move(_VSTD::forward<_Ip>(__i)); -}; +template +concept __unqualified_iter_move = + __class_or_enum> && + requires (_Tp&& __t) { + iter_move(_VSTD::forward<_Tp>(__t)); + }; // [iterator.cust.move]/1 // The name ranges::iter_move denotes a customization point object. @@ -72,20 +75,19 @@ struct __fn { // [iterator.cust.move]/1.3 // Otherwise, ranges::iter_move(E) is ill-formed. }; -} // namespace ranges::__iter_move +} // namespace __iter_move -namespace ranges::inline __cpo { +inline namespace __cpo { inline constexpr auto iter_move = __iter_move::__fn{}; -} +} // namespace __cpo +} // namespace ranges template<__dereferenceable _Tp> -requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __referenceable; } + requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __referenceable; } using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<_Tp&>())); -#endif // !_LIBCPP_HAS_NO_RANGES +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _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 d70da09b4a..0b290520b7 100644 --- a/lib/libcxx/include/__iterator/iter_swap.h +++ b/lib/libcxx/include/__iterator/iter_swap.h @@ -14,7 +14,8 @@ #include <__iterator/iter_move.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> -#include <__ranges/access.h> +#include <__utility/forward.h> +#include <__utility/move.h> #include #include @@ -22,12 +23,11 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [iter.cust.swap] namespace ranges { namespace __iter_swap { @@ -35,9 +35,11 @@ namespace __iter_swap { void iter_swap(_I1, _I2) = delete; template - concept __unqualified_iter_swap = requires(_T1&& __x, _T2&& __y) { - iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); - }; + concept __unqualified_iter_swap = + (__class_or_enum> || __class_or_enum>) && + requires (_T1&& __x, _T2&& __y) { + iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); + }; template concept __readable_swappable = @@ -80,12 +82,11 @@ namespace __iter_swap { *_VSTD::forward<_T1>(__x) = _VSTD::move(__old); } }; -} // end namespace __iter_swap +} // namespace __iter_swap inline namespace __cpo { inline constexpr auto iter_swap = __iter_swap::__fn{}; } // namespace __cpo - } // namespace ranges template @@ -98,10 +99,8 @@ concept indirectly_swappable = ranges::iter_swap(__i2, __i1); }; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_ITER_SWAP_H diff --git a/lib/libcxx/include/__iterator/iterator.h b/lib/libcxx/include/__iterator/iterator.h index dfd481e357..be298ee522 100644 --- a/lib/libcxx/include/__iterator/iterator.h +++ b/lib/libcxx/include/__iterator/iterator.h @@ -17,9 +17,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) template using __with_reference = _Tp&; @@ -44,7 +41,7 @@ concept __dereferenceable = requires(_Tp& __t) { template<__dereferenceable _Tp> using iter_reference_t = decltype(*declval<_Tp&>()); -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) template struct _LIBCPP_TEMPLATE_VIS iterator_traits; @@ -79,7 +76,7 @@ struct __iter_concept_category_test { }; struct __iter_concept_random_fallback { template - using _Apply = _EnableIf< + using _Apply = __enable_if_t< __is_primary_template >::value, random_access_iterator_tag >; @@ -142,7 +139,7 @@ public: static const bool value = sizeof(__test<_Tp>(nullptr)) == 1; }; -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) // The `cpp17-*-iterator` exposition-only concepts are easily confused with the Cpp17*Iterator tables, // so they've been banished to a namespace that makes it obvious they have a niche use-case. @@ -365,7 +362,7 @@ struct iterator_traits : __iterator_traits<_Ip> { using __primary_template = iterator_traits; }; -#else // !defined(_LIBCPP_HAS_NO_RANGES) +#else // !defined(_LIBCPP_HAS_NO_CONCEPTS) template struct __iterator_traits {}; @@ -402,10 +399,10 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits using __primary_template = iterator_traits; }; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) template -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) requires is_object_v<_Tp> #endif struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> @@ -477,7 +474,7 @@ struct __is_exactly_cpp17_input_iterator __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; -#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +#if _LIBCPP_STD_VER >= 17 template using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; @@ -491,10 +488,8 @@ template using __iter_to_alloc_type = pair< add_const_t::value_type::first_type>, typename iterator_traits<_InputIterator>::value_type::second_type>; -#endif // _LIBCPP_HAS_NO_DEDUCTION_GUIDES +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H diff --git a/lib/libcxx/include/__iterator/move_iterator.h b/lib/libcxx/include/__iterator/move_iterator.h index 7819743bdb..29bac864c2 100644 --- a/lib/libcxx/include/__iterator/move_iterator.h +++ b/lib/libcxx/include/__iterator/move_iterator.h @@ -12,33 +12,32 @@ #include <__config> #include <__iterator/iterator_traits.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 class _LIBCPP_TEMPLATE_VIS move_iterator { -private: - _Iter __i; public: - typedef _Iter iterator_type; +#if _LIBCPP_STD_VER > 17 + typedef input_iterator_tag iterator_concept; +#endif + + typedef _Iter iterator_type; + typedef _If< + __is_cpp17_random_access_iterator<_Iter>::value, + random_access_iterator_tag, + typename iterator_traits<_Iter>::iterator_category + > iterator_category; typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::difference_type difference_type; typedef iterator_type pointer; - typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, - random_access_iterator_tag, - typename iterator_traits<_Iter>::iterator_category> iterator_category; -#if _LIBCPP_STD_VER > 17 - typedef input_iterator_tag iterator_concept; -#endif #ifndef _LIBCPP_CXX03_LANG typedef typename iterator_traits::reference __reference; @@ -51,114 +50,113 @@ public: typedef typename iterator_traits::reference reference; #endif - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator() : __i() {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator() : __current_() {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - explicit move_iterator(_Iter __x) : __i(__x) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + explicit move_iterator(_Iter __i) : __current_(_VSTD::move(__i)) {} - template ::value && is_convertible<_Up const&, _Iter>::value + template ::value && is_convertible::value > > - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} - template ::value && - is_convertible<_Up const&, _Iter>::value && - is_assignable<_Iter&, _Up const&>::value + is_convertible::value && + is_assignable<_Iter&, const _Up&>::value > > - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 move_iterator& operator=(const move_iterator<_Up>& __u) { - __i = __u.base(); + __current_ = __u.base(); return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reference operator*() const { return static_cast(*__i); } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - pointer operator->() const { return __i;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator& operator++() {++__i; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator operator++(int) {move_iterator __tmp(*this); ++__i; return __tmp;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator& operator--() {--__i; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator operator--(int) {move_iterator __tmp(*this); --__i; return __tmp;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator operator+ (difference_type __n) const {return move_iterator(__i + __n);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator& operator+=(difference_type __n) {__i += __n; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator operator- (difference_type __n) const {return move_iterator(__i - __n);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator& operator-=(difference_type __n) {__i -= __n; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reference operator[](difference_type __n) const { return static_cast(__i[__n]); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + _Iter base() const { return __current_; } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + reference operator*() const { return static_cast(*__current_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + pointer operator->() const { return __current_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + reference operator[](difference_type __n) const { return static_cast(__current_[__n]); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator& operator++() { ++__current_; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator& operator--() { --__current_; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator operator--(int) { move_iterator __tmp(*this); --__current_; return __tmp; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator operator+(difference_type __n) const { return move_iterator(__current_ + __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator& operator+=(difference_type __n) { __current_ += __n; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator operator-(difference_type __n) const { return move_iterator(__current_ - __n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } + +private: + _Iter __current_; }; template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() == __y.base(); } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ - return __x.base() < __y.base(); -} - -template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() != __y.base(); } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() < __y.base(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() > __y.base(); } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ - return __x.base() >= __y.base(); -} - -template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -bool -operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() <= __y.base(); } +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) +{ + return __x.base() >= __y.base(); +} + #ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -auto -operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) --> decltype(__x.base() - __y.base()) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 +auto operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) + -> decltype(__x.base() - __y.base()) { return __x.base() - __y.base(); } #else template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI typename move_iterator<_Iter1>::difference_type operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { @@ -167,7 +165,7 @@ operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) #endif template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 move_iterator<_Iter> operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) { @@ -175,15 +173,13 @@ operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterato } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 move_iterator<_Iter> make_move_iterator(_Iter __i) { - return move_iterator<_Iter>(__i); + return move_iterator<_Iter>(_VSTD::move(__i)); } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/next.h b/lib/libcxx/include/__iterator/next.h index 1eecaa9750..5dda0674d5 100644 --- a/lib/libcxx/include/__iterator/next.h +++ b/lib/libcxx/include/__iterator/next.h @@ -12,7 +12,6 @@ #include <__config> #include <__debug> -#include <__function_like.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> @@ -23,9 +22,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -39,13 +35,14 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 return __x; } -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +// [range.iter.op.next] namespace ranges { -struct __next_fn final : private __function_like { - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __next_fn(__tag __x) noexcept : __function_like(__x) {} +namespace __next { +struct __fn { template _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x) const { @@ -75,13 +72,15 @@ struct __next_fn final : private __function_like { } }; -inline constexpr auto next = __next_fn(__function_like::__tag()); +} // namespace __next + +inline namespace __cpo { + inline constexpr auto next = __next::__fn{}; +} // namespace __cpo } // namespace ranges -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ITERATOR_PRIMITIVES_H +#endif // _LIBCPP___ITERATOR_NEXT_H diff --git a/lib/libcxx/include/__iterator/ostream_iterator.h b/lib/libcxx/include/__iterator/ostream_iterator.h index 5b4466c863..20a36742cc 100644 --- a/lib/libcxx/include/__iterator/ostream_iterator.h +++ b/lib/libcxx/include/__iterator/ostream_iterator.h @@ -20,9 +20,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -70,6 +67,4 @@ public: _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/ostreambuf_iterator.h b/lib/libcxx/include/__iterator/ostreambuf_iterator.h index 90309dacd4..3272f6c99d 100644 --- a/lib/libcxx/include/__iterator/ostreambuf_iterator.h +++ b/lib/libcxx/include/__iterator/ostreambuf_iterator.h @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -76,6 +73,4 @@ public: _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/prev.h b/lib/libcxx/include/__iterator/prev.h index cb8a571355..2b8c15fe57 100644 --- a/lib/libcxx/include/__iterator/prev.h +++ b/lib/libcxx/include/__iterator/prev.h @@ -12,7 +12,6 @@ #include <__config> #include <__debug> -#include <__function_like.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> @@ -23,9 +22,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -38,13 +34,14 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 return __x; } -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +// [range.iter.op.prev] namespace ranges { -struct __prev_fn final : private __function_like { - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __prev_fn(__tag __x) noexcept : __function_like(__x) {} +namespace __prev { +struct __fn { template _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __x) const { @@ -67,13 +64,15 @@ struct __prev_fn final : private __function_like { } }; -inline constexpr auto prev = __prev_fn(__function_like::__tag()); +} // namespace __prev + +inline namespace __cpo { + inline constexpr auto prev = __prev::__fn{}; +} // namespace __cpo } // namespace ranges -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_PREV_H diff --git a/lib/libcxx/include/__iterator/projected.h b/lib/libcxx/include/__iterator/projected.h index 7064a5eb91..30ea3a124b 100644 --- a/lib/libcxx/include/__iterator/projected.h +++ b/lib/libcxx/include/__iterator/projected.h @@ -18,12 +18,9 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) template _Proj> struct projected { @@ -36,10 +33,8 @@ struct incrementable_traits> { using difference_type = iter_difference_t<_It>; }; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_PROJECTED_H diff --git a/lib/libcxx/include/__iterator/readable_traits.h b/lib/libcxx/include/__iterator/readable_traits.h index fbad106e4e..c0b16bafd7 100644 --- a/lib/libcxx/include/__iterator/readable_traits.h +++ b/lib/libcxx/include/__iterator/readable_traits.h @@ -18,12 +18,9 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_HAS_NO_RANGES) +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) // [readable.traits] template struct __cond_value_type {}; @@ -60,14 +57,14 @@ template<__has_member_element_type _Tp> struct indirectly_readable_traits<_Tp> : __cond_value_type {}; -// Pre-emptively applies LWG3541 template<__has_member_value_type _Tp> -requires __has_member_element_type<_Tp> + requires __has_member_element_type<_Tp> struct indirectly_readable_traits<_Tp> {}; + template<__has_member_value_type _Tp> -requires __has_member_element_type<_Tp> && - same_as, - remove_cv_t> + requires __has_member_element_type<_Tp> && + same_as, + remove_cv_t> struct indirectly_readable_traits<_Tp> : __cond_value_type {}; @@ -82,10 +79,8 @@ using iter_value_t = typename conditional_t<__is_primary_template >, iterator_traits > >::value_type; -#endif // !defined(_LIBCPP_HAS_NO_RANGES) +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H diff --git a/lib/libcxx/include/__iterator/reverse_access.h b/lib/libcxx/include/__iterator/reverse_access.h index 66cc3568c1..643aede01c 100644 --- a/lib/libcxx/include/__iterator/reverse_access.h +++ b/lib/libcxx/include/__iterator/reverse_access.h @@ -19,9 +19,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_CXX03_LANG) @@ -104,6 +101,4 @@ auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_REVERSE_ACCESS_H diff --git a/lib/libcxx/include/__iterator/reverse_iterator.h b/lib/libcxx/include/__iterator/reverse_iterator.h index 76424a89a1..af855a0a1e 100644 --- a/lib/libcxx/include/__iterator/reverse_iterator.h +++ b/lib/libcxx/include/__iterator/reverse_iterator.h @@ -10,6 +10,8 @@ #ifndef _LIBCPP___ITERATOR_REVERSE_ITERATOR_H #define _LIBCPP___ITERATOR_REVERSE_ITERATOR_H +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> #include <__config> #include <__iterator/iterator.h> #include <__iterator/iterator_traits.h> @@ -20,18 +22,8 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -template -struct __is_stashing_iterator : false_type {}; - -template -struct __is_stashing_iterator<_Tp, typename __void_t::type> - : true_type {}; - _LIBCPP_SUPPRESS_DEPRECATED_PUSH template class _LIBCPP_TEMPLATE_VIS reverse_iterator @@ -49,10 +41,6 @@ private: _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break #endif - static_assert(!__is_stashing_iterator<_Iter>::value, - "The specified iterator type cannot be used with reverse_iterator; " - "Using stashing iterators with reverse_iterator causes undefined behavior"); - protected: _Iter current; public: @@ -78,7 +66,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {} - template ::value && is_convertible<_Up const&, _Iter>::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -86,10 +74,10 @@ public: : __t(__u.base()), current(__u.base()) { } - template ::value && is_convertible<_Up const&, _Iter>::value && - is_assignable<_Up const&, _Iter>::value + is_assignable<_Iter&, _Up const&>::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { @@ -103,7 +91,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 explicit reverse_iterator(_Iter __x) : current(__x) {} - template ::value && is_convertible<_Up const&, _Iter>::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -111,10 +99,10 @@ public: : current(__u.base()) { } - template ::value && is_convertible<_Up const&, _Iter>::value && - is_assignable<_Up const&, _Iter>::value + is_assignable<_Iter&, _Up const&>::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { @@ -196,6 +184,16 @@ operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& return __x.base() >= __y.base(); } +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) +template _Iter2> +_LIBCPP_HIDE_FROM_ABI constexpr +compare_three_way_result_t<_Iter1, _Iter2> +operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) +{ + return __y.base() <=> __x.base(); +} +#endif + #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -234,6 +232,4 @@ reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_REVERSE_ITERATOR_H diff --git a/lib/libcxx/include/__iterator/size.h b/lib/libcxx/include/__iterator/size.h index 259424f1d3..2e6a7d386c 100644 --- a/lib/libcxx/include/__iterator/size.h +++ b/lib/libcxx/include/__iterator/size.h @@ -18,9 +18,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 @@ -53,6 +50,4 @@ constexpr ptrdiff_t ssize(const _Tp (&)[_Sz]) noexcept { return _Sz; } _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_SIZE_H diff --git a/lib/libcxx/include/__iterator/unreachable_sentinel.h b/lib/libcxx/include/__iterator/unreachable_sentinel.h new file mode 100644 index 0000000000..b200236d8b --- /dev/null +++ b/lib/libcxx/include/__iterator/unreachable_sentinel.h @@ -0,0 +1,38 @@ +// -*- 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_UNREACHABLE_SENTINEL_H +#define _LIBCPP___ITERATOR_UNREACHABLE_SENTINEL_H + +#include <__config> +#include <__iterator/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +struct unreachable_sentinel_t { + template + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(unreachable_sentinel_t, const _Iter&) noexcept { + return false; + } +}; + +inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_UNREACHABLE_SENTINEL_H diff --git a/lib/libcxx/include/__iterator/wrap_iter.h b/lib/libcxx/include/__iterator/wrap_iter.h index e35a372b42..d9dbee5888 100644 --- a/lib/libcxx/include/__iterator/wrap_iter.h +++ b/lib/libcxx/include/__iterator/wrap_iter.h @@ -13,16 +13,14 @@ #include <__config> #include <__debug> #include <__iterator/iterator_traits.h> -#include <__memory/pointer_traits.h> // __to_address +#include <__memory/addressof.h> +#include <__memory/pointer_traits.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 @@ -42,120 +40,109 @@ public: private: iterator_type __i; public: - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 - : __i{} -#endif + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter() _NOEXCEPT + : __i() { -#if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__insert_i(this); -#endif + _VSTD::__debug_db_insert_i(this); } - template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter(const __wrap_iter<_Up>& __u, typename enable_if::value>::type* = nullptr) _NOEXCEPT : __i(__u.base()) { #if _LIBCPP_DEBUG_LEVEL == 2 - __get_db()->__iterator_copy(this, &__u); + if (!__libcpp_is_constant_evaluated()) + __get_db()->__iterator_copy(this, _VSTD::addressof(__u)); #endif } #if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter(const __wrap_iter& __x) : __i(__x.base()) { - __get_db()->__iterator_copy(this, &__x); + if (!__libcpp_is_constant_evaluated()) + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter& operator=(const __wrap_iter& __x) { - if (this != &__x) + if (this != _VSTD::addressof(__x)) { - __get_db()->__iterator_copy(this, &__x); + if (!__libcpp_is_constant_evaluated()) + __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); __i = __x.__i; } return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__wrap_iter() { + if (!__libcpp_is_constant_evaluated()) __get_db()->__erase_i(this); } #endif - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 reference operator*() const _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable iterator"); return *__i; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 pointer operator->() const _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable iterator"); return _VSTD::__to_address(__i); } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter& operator++() _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable iterator"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment a non-incrementable iterator"); ++__i; return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter operator++(int) _NOEXCEPT {__wrap_iter __tmp(*this); ++(*this); return __tmp;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter& operator--() _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), - "Attempted to decrement a non-decrementable iterator"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this), + "Attempted to decrement a non-decrementable iterator"); --__i; return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter operator--(int) _NOEXCEPT {__wrap_iter __tmp(*this); --(*this); return __tmp;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter operator+ (difference_type __n) const _NOEXCEPT {__wrap_iter __w(*this); __w += __n; return __w;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter& operator+=(difference_type __n) _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__addable(this, __n), - "Attempted to add/subtract an iterator outside its valid range"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__addable(this, __n), + "Attempted to add/subtract an iterator outside its valid range"); __i += __n; return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter operator- (difference_type __n) const _NOEXCEPT {return *this + (-__n);} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter& operator-=(difference_type __n) _NOEXCEPT {*this += -__n; return *this;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 reference operator[](difference_type __n) const _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__subscriptable(this, __n), - "Attempted to subscript an iterator outside its valid range"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__subscriptable(this, __n), + "Attempted to subscript an iterator outside its valid range"); return __i[__n]; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT {return __i;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 iterator_type base() const _NOEXCEPT {return __i;} private: #if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(const void* __p, iterator_type __x) : __i(__x) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter(const void* __p, iterator_type __x) : __i(__x) { + if (!__libcpp_is_constant_evaluated()) __get_db()->__insert_ic(this, __p); } #else - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} #endif template friend class __wrap_iter; @@ -165,99 +152,95 @@ private: }; template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { return __x.base() == __y.base(); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { return __x.base() == __y.base(); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), - "Attempted to compare incomparable iterators"); -#endif + _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(); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), - "Attempted to compare incomparable iterators"); -#endif + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), + "Attempted to compare incomparable iterators"); return __x.base() < __y.base(); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { return !(__x == __y); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { return !(__x == __y); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { return __y < __x; } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { return __y < __x; } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { return !(__x < __y); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { return !(__x < __y); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { return !(__y < __x); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { return !(__y < __x); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 #ifndef _LIBCPP_CXX03_LANG auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT -> decltype(__x.base() - __y.base()) @@ -266,15 +249,13 @@ typename __wrap_iter<_Iter1>::difference_type operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT #endif // C++03 { -#if _LIBCPP_DEBUG_LEVEL == 2 - _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), - "Attempted to subtract incompatible iterators"); -#endif + _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(); } template -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type __n, __wrap_iter<_Iter1> __x) _NOEXCEPT { __x += __n; @@ -286,15 +267,19 @@ template struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {}; #endif -template -_LIBCPP_CONSTEXPR -decltype(_VSTD::__to_address(declval<_Iter>())) -__to_address(__wrap_iter<_Iter> __w) _NOEXCEPT { - return _VSTD::__to_address(__w.base()); -} +template +struct _LIBCPP_TEMPLATE_VIS pointer_traits<__wrap_iter<_It> > +{ + typedef __wrap_iter<_It> pointer; + typedef typename pointer_traits<_It>::element_type element_type; + typedef typename pointer_traits<_It>::difference_type difference_type; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + static element_type *to_address(pointer __w) _NOEXCEPT { + return _VSTD::__to_address(__w.base()); + } +}; _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___ITERATOR_WRAP_ITER_H diff --git a/lib/libcxx/include/__libcpp_version b/lib/libcxx/include/__libcpp_version index 09514aa4db..bfed819398 100644 --- a/lib/libcxx/include/__libcpp_version +++ b/lib/libcxx/include/__libcpp_version @@ -1 +1 @@ -13000 +14000 diff --git a/lib/libcxx/include/__locale b/lib/libcxx/include/__locale index 0a99f824ec..51f35eece7 100644 --- a/lib/libcxx/include/__locale +++ b/lib/libcxx/include/__locale @@ -12,18 +12,17 @@ #include <__availability> #include <__config> -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include + #if defined(_LIBCPP_MSVCRT_LIKE) # include # include <__support/win32/locale_win32.h> -#elif defined(__NuttX__) -# include <__support/nuttx/xlocale.h> #elif defined(_AIX) || defined(__MVS__) # include <__support/ibm/xlocale.h> #elif defined(__ANDROID__) @@ -35,7 +34,7 @@ # include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) # include <__support/openbsd/xlocale.h> -#elif (defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) \ +#elif (defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) # include #elif defined(__Fuchsia__) @@ -210,10 +209,11 @@ class _LIBCPP_TYPE_VIS locale::id static int32_t __next_id; public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR id() :__id_(0) {} + void operator=(const id&) = delete; + id(const id&) = delete; + private: void __init(); - void operator=(const id&); // = delete; - id(const id&); // = delete; public: // only needed for tests long __get(); @@ -340,7 +340,9 @@ collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const } _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate) +#endif // template class collate_byname; @@ -365,6 +367,7 @@ protected: virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const; }; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS collate_byname : public collate @@ -384,6 +387,7 @@ protected: const char_type* __lo2, const char_type* __hi2) const; virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const; }; +#endif template bool @@ -448,12 +452,12 @@ public: static const mask punct = _PUNCT; static const mask xdigit = _HEX; static const mask blank = _BLANK; - static const mask __regex_word = 0x80; + static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT -#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__DragonFly__) +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) # ifdef __APPLE__ typedef __uint32_t mask; -# elif defined(__FreeBSD__) || defined(__DragonFly__) +# elif defined(__FreeBSD__) typedef unsigned long mask; # elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) typedef unsigned short mask; @@ -507,6 +511,33 @@ public: # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT +#elif defined(__MVS__) +# if defined(__NATIVE_ASCII_F) + typedef unsigned int mask; + static const mask space = _ISSPACE_A; + static const mask print = _ISPRINT_A; + static const mask cntrl = _ISCNTRL_A; + static const mask upper = _ISUPPER_A; + static const mask lower = _ISLOWER_A; + static const mask alpha = _ISALPHA_A; + static const mask digit = _ISDIGIT_A; + static const mask punct = _ISPUNCT_A; + static const mask xdigit = _ISXDIGIT_A; + static const mask blank = _ISBLANK_A; +# else + typedef unsigned short mask; + static const mask space = __ISSPACE; + static const mask print = __ISPRINT; + static const mask cntrl = __ISCNTRL; + static const mask upper = __ISUPPER; + static const mask lower = __ISLOWER; + static const mask alpha = __ISALPHA; + static const mask digit = __ISDIGIT; + static const mask punct = __ISPUNCT; + static const mask xdigit = __ISXDIGIT; + static const mask blank = __ISBLANK; +# endif + static const mask __regex_word = 0x8000; #else # error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE? #endif @@ -514,10 +545,17 @@ public: static const mask graph = alnum | punct; _LIBCPP_INLINE_VISIBILITY ctype_base() {} + +// TODO: Remove the ifndef when the assert no longer fails on AIX. +#ifndef _AIX + static_assert((__regex_word & ~(space | print | cntrl | upper | lower | alpha | digit | punct | xdigit | blank)) == __regex_word, + "__regex_word can't overlap other bits"); +#endif }; template class _LIBCPP_TEMPLATE_VIS ctype; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS ctype : public locale::facet, @@ -619,6 +657,7 @@ protected: virtual char do_narrow(char_type, char __dfault) const; virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const; }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS ctype @@ -728,6 +767,10 @@ public: static const short* __classic_upper_table() _NOEXCEPT; static const short* __classic_lower_table() _NOEXCEPT; #endif +#if defined(__MVS__) + static const unsigned short* __classic_upper_table() _NOEXCEPT; + static const unsigned short* __classic_lower_table() _NOEXCEPT; +#endif protected: ~ctype(); @@ -763,6 +806,7 @@ protected: virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const; }; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS ctype_byname : public ctype @@ -788,6 +832,7 @@ protected: virtual char do_narrow(char_type, char __dfault) const; virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const; }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template inline _LIBCPP_INLINE_VISIBILITY @@ -994,6 +1039,7 @@ protected: // template <> class codecvt +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS codecvt : public locale::facet, @@ -1074,6 +1120,7 @@ protected: virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const; virtual int do_max_length() const _NOEXCEPT; }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS // template <> class codecvt // deprecated in C++20 @@ -1452,7 +1499,9 @@ codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname) +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname) +#endif _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname) // deprecated in C++20 _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname) // deprecated in C++20 #ifndef _LIBCPP_HAS_NO_CHAR8_T @@ -1683,6 +1732,7 @@ protected: string __grouping_; }; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS numpunct : public locale::facet @@ -1713,6 +1763,7 @@ protected: char_type __thousands_sep_; string __grouping_; }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS // template class numpunct_byname @@ -1736,6 +1787,7 @@ private: void __init(const char*); }; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> class _LIBCPP_TYPE_VIS numpunct_byname : public numpunct @@ -1753,6 +1805,7 @@ protected: private: void __init(const char*); }; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__mbstate_t.h b/lib/libcxx/include/__mbstate_t.h new file mode 100644 index 0000000000..3489f9cc0e --- /dev/null +++ b/lib/libcxx/include/__mbstate_t.h @@ -0,0 +1,44 @@ +// -*- 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___MBSTATE_T_H +#define _LIBCPP___MBSTATE_T_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#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. +// +// This is a gruesome hack, but I don't know how to make it cleaner for +// the time being. + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include // for mbstate_t +#elif __has_include() +# include // works on most Unixes +#elif __has_include() +# include // works on Darwin +#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." +#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/__memory/addressof.h b/lib/libcxx/include/__memory/addressof.h index 5efdb58786..c45dedfaec 100644 --- a/lib/libcxx/include/__memory/addressof.h +++ b/lib/libcxx/include/__memory/addressof.h @@ -16,13 +16,8 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF - template inline _LIBCPP_CONSTEXPR_AFTER_CXX14 _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY @@ -32,19 +27,6 @@ addressof(_Tp& __x) _NOEXCEPT return __builtin_addressof(__x); } -#else - -template -inline _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY -_Tp* -addressof(_Tp& __x) _NOEXCEPT -{ - return reinterpret_cast<_Tp *>( - const_cast(&reinterpret_cast(__x))); -} - -#endif // _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF - #if defined(_LIBCPP_HAS_OBJC_ARC) && !defined(_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF) // Objective-C++ Automatic Reference Counting uses qualified pointers // that require special addressof() signatures. When @@ -91,6 +73,4 @@ template _Tp* addressof(const _Tp&&) noexcept = delete; _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___MEMORY_ADDRESSOF_H diff --git a/lib/libcxx/include/__memory/allocation_guard.h b/lib/libcxx/include/__memory/allocation_guard.h index 4987af293d..6412677aaf 100644 --- a/lib/libcxx/include/__memory/allocation_guard.h +++ b/lib/libcxx/include/__memory/allocation_guard.h @@ -19,10 +19,6 @@ #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 @@ -84,6 +80,4 @@ 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 2c21a16e7e..708bd82b02 100644 --- a/lib/libcxx/include/__memory/allocator.h +++ b/lib/libcxx/include/__memory/allocator.h @@ -22,9 +22,6 @@ #pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template class allocator; @@ -83,6 +80,7 @@ template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator<_Tp> > { + static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types"); public: typedef size_t size_type; typedef ptrdiff_t difference_type; @@ -91,7 +89,7 @@ public: typedef true_type is_always_equal; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - allocator() _NOEXCEPT _LIBCPP_DEFAULT + allocator() _NOEXCEPT = default; template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -100,8 +98,7 @@ public: _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) - __throw_length_error("allocator::allocate(size_t n)" - " 'n' exceeds maximum supported size"); + __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } else { @@ -165,6 +162,7 @@ template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator > { + static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types"); public: typedef size_t size_type; typedef ptrdiff_t difference_type; @@ -173,7 +171,7 @@ public: typedef true_type is_always_equal; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - allocator() _NOEXCEPT _LIBCPP_DEFAULT + allocator() _NOEXCEPT = default; template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 @@ -182,8 +180,7 @@ public: _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) - __throw_length_error("allocator::allocate(size_t n)" - " 'n' exceeds maximum supported size"); + __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { return static_cast(::operator new(__n * sizeof(_Tp))); } else { @@ -249,6 +246,4 @@ bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #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 830c6b8148..f5a116dbbd 100644 --- a/lib/libcxx/include/__memory/allocator_arg_t.h +++ b/lib/libcxx/include/__memory/allocator_arg_t.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H -#define _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H +#ifndef _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H +#define _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H #include <__config> #include <__memory/uses_allocator.h> @@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = defau #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; #else -/* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +/* inline */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); #endif #ifndef _LIBCPP_CXX03_LANG @@ -36,7 +36,7 @@ extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; template struct __uses_alloc_ctor_imp { - typedef _LIBCPP_NODEBUG_TYPE typename __uncvref<_Alloc>::type _RawAlloc; + typedef _LIBCPP_NODEBUG typename __uncvref<_Alloc>::type _RawAlloc; static const bool __ua = uses_allocator<_Tp, _RawAlloc>::value; static const bool __ic = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; @@ -75,4 +75,4 @@ void __user_alloc_construct_impl (integral_constant, _Tp *__storage, con _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H +#endif // _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H diff --git a/lib/libcxx/include/__memory/allocator_traits.h b/lib/libcxx/include/__memory/allocator_traits.h index a02af0deaf..f4c8fa02d6 100644 --- a/lib/libcxx/include/__memory/allocator_traits.h +++ b/lib/libcxx/include/__memory/allocator_traits.h @@ -36,11 +36,11 @@ template ::type, bool = __has_pointer<_RawAlloc>::value> struct __pointer { - using type _LIBCPP_NODEBUG_TYPE = typename _RawAlloc::pointer; + using type _LIBCPP_NODEBUG = typename _RawAlloc::pointer; }; template struct __pointer<_Tp, _Alloc, _RawAlloc, false> { - using type _LIBCPP_NODEBUG_TYPE = _Tp*; + using type _LIBCPP_NODEBUG = _Tp*; }; // __const_pointer @@ -48,14 +48,14 @@ _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_pointer, const_pointer); template ::value> struct __const_pointer { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::const_pointer; + using type _LIBCPP_NODEBUG = typename _Alloc::const_pointer; }; template struct __const_pointer<_Tp, _Ptr, _Alloc, false> { #ifdef _LIBCPP_CXX03_LANG using type = typename pointer_traits<_Ptr>::template rebind::other; #else - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::template rebind; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; #endif }; @@ -64,14 +64,14 @@ _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_void_pointer, void_pointer); template ::value> struct __void_pointer { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::void_pointer; + using type _LIBCPP_NODEBUG = typename _Alloc::void_pointer; }; template struct __void_pointer<_Ptr, _Alloc, false> { #ifdef _LIBCPP_CXX03_LANG - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::template rebind::other; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind::other; #else - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::template rebind; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; #endif }; @@ -80,14 +80,14 @@ _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_void_pointer, const_void_pointer); template ::value> struct __const_void_pointer { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::const_void_pointer; + using type _LIBCPP_NODEBUG = typename _Alloc::const_void_pointer; }; template struct __const_void_pointer<_Ptr, _Alloc, false> { #ifdef _LIBCPP_CXX03_LANG - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::template rebind::other; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind::other; #else - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::template rebind; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind; #endif }; @@ -97,18 +97,18 @@ template ::value> struct __size_type : make_unsigned<_DiffType> { }; template struct __size_type<_Alloc, _DiffType, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::size_type; + using type _LIBCPP_NODEBUG = typename _Alloc::size_type; }; // __alloc_traits_difference_type _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_alloc_traits_difference_type, difference_type); template ::value> struct __alloc_traits_difference_type { - using type _LIBCPP_NODEBUG_TYPE = typename pointer_traits<_Ptr>::difference_type; + using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::difference_type; }; template struct __alloc_traits_difference_type<_Alloc, _Ptr, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::difference_type; + using type _LIBCPP_NODEBUG = typename _Alloc::difference_type; }; // __propagate_on_container_copy_assignment @@ -117,7 +117,7 @@ template struct __propagate_on_container_copy_assignment<_Alloc, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::propagate_on_container_copy_assignment; + using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_copy_assignment; }; // __propagate_on_container_move_assignment @@ -126,7 +126,7 @@ template struct __propagate_on_container_move_assignment<_Alloc, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::propagate_on_container_move_assignment; + using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_move_assignment; }; // __propagate_on_container_swap @@ -135,7 +135,7 @@ template ::value> struct __propagate_on_container_swap : false_type { }; template struct __propagate_on_container_swap<_Alloc, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::propagate_on_container_swap; + using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_swap; }; // __is_always_equal @@ -144,7 +144,7 @@ template ::value> struct __is_always_equal : is_empty<_Alloc> { }; template struct __is_always_equal<_Alloc, true> { - using type _LIBCPP_NODEBUG_TYPE = typename _Alloc::is_always_equal; + using type _LIBCPP_NODEBUG = typename _Alloc::is_always_equal; }; // __allocator_traits_rebind @@ -158,15 +158,15 @@ struct __has_rebind_other<_Tp, _Up, typename __void_t< template ::value> struct __allocator_traits_rebind { - using type _LIBCPP_NODEBUG_TYPE = typename _Tp::template rebind<_Up>::other; + using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other; }; template