libcxx: update to LLVM 22

This commit is contained in:
Alex Rønne Petersen
2026-01-17 05:40:55 +01:00
parent 80212b03ff
commit dfabf1586f
425 changed files with 15930 additions and 10446 deletions
+11 -5
View File
@@ -10,24 +10,28 @@
#ifndef _LIBCPP___ALGORITHM_ALL_OF_H #ifndef _LIBCPP___ALGORITHM_ALL_OF_H
#define _LIBCPP___ALGORITHM_ALL_OF_H #define _LIBCPP___ALGORITHM_ALL_OF_H
#include <__algorithm/any_of.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Iter, class _Sent, class _Proj, class _Pred> template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
__all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { __all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) { using _Ref = decltype(std::__invoke(__proj, *__first));
if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) auto __negated_pred = [&__pred](_Ref __arg) -> bool { return !std::__invoke(__pred, std::forward<_Ref>(__arg)); };
return false; return !std::__any_of(std::move(__first), std::move(__last), __negated_pred, __proj);
}
return true;
} }
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
@@ -39,4 +43,6 @@ all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_ALL_OF_H #endif // _LIBCPP___ALGORITHM_ALL_OF_H
+4
View File
@@ -11,6 +11,7 @@
#include <__config> #include <__config>
#include <__type_traits/desugars_to.h> #include <__type_traits/desugars_to.h>
#include <__type_traits/is_generic_transparent_comparator.h>
#include <__type_traits/is_integral.h> #include <__type_traits/is_integral.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -48,6 +49,9 @@ inline const bool __desugars_to_v<__less_tag, __less<>, _Tp, _Tp> = true;
template <class _Tp> template <class _Tp>
inline const bool __desugars_to_v<__totally_ordered_less_tag, __less<>, _Tp, _Tp> = is_integral<_Tp>::value; inline const bool __desugars_to_v<__totally_ordered_less_tag, __less<>, _Tp, _Tp> = is_integral<_Tp>::value;
template <>
inline const bool __is_generic_transparent_comparator_v<__less<> > = true;
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_COMP_H #endif // _LIBCPP___ALGORITHM_COMP_H
+28 -147
View File
@@ -12,11 +12,10 @@
#include <__algorithm/copy_move_common.h> #include <__algorithm/copy_move_common.h>
#include <__algorithm/for_each_segment.h> #include <__algorithm/for_each_segment.h>
#include <__algorithm/min.h> #include <__algorithm/min.h>
#include <__algorithm/specialized_algorithms.h>
#include <__config> #include <__config>
#include <__fwd/bit_reference.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h> #include <__iterator/segmented_iterator.h>
#include <__memory/pointer_traits.h>
#include <__type_traits/common_type.h> #include <__type_traits/common_type.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__utility/move.h> #include <__utility/move.h>
@@ -38,124 +37,14 @@ copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result);
template <class _InIter, class _Sent, class _OutIter> template <class _InIter, class _Sent, class _OutIter>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter);
template <class _Cp, bool _IsConst>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned(
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
using _In = __bit_iterator<_Cp, _IsConst>;
using difference_type = typename _In::difference_type;
using __storage_type = typename _In::__storage_type;
const int __bits_per_word = _In::__bits_per_word;
difference_type __n = __last - __first;
if (__n > 0) {
// do first word
if (__first.__ctz_ != 0) {
unsigned __clz = __bits_per_word - __first.__ctz_;
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
__n -= __dn;
__storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first.__ctz_);
__storage_type __b = *__first.__seg_ & __m;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b;
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
++__first.__seg_;
// __first.__ctz_ = 0;
}
// __first.__ctz_ == 0;
// do middle words
__storage_type __nw = __n / __bits_per_word;
std::copy(std::__to_address(__first.__seg_),
std::__to_address(__first.__seg_ + __nw),
std::__to_address(__result.__seg_));
__n -= __nw * __bits_per_word;
__result.__seg_ += __nw;
// do last word
if (__n > 0) {
__first.__seg_ += __nw;
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
__storage_type __b = *__first.__seg_ & __m;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b;
__result.__ctz_ = static_cast<unsigned>(__n);
}
}
return __result;
}
template <class _Cp, bool _IsConst>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned(
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
using _In = __bit_iterator<_Cp, _IsConst>;
using difference_type = typename _In::difference_type;
using __storage_type = typename _In::__storage_type;
const int __bits_per_word = _In::__bits_per_word;
difference_type __n = __last - __first;
if (__n > 0) {
// do first word
if (__first.__ctz_ != 0) {
unsigned __clz_f = __bits_per_word - __first.__ctz_;
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
__n -= __dn;
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
__storage_type __b = *__first.__seg_ & __m;
unsigned __clz_r = __bits_per_word - __result.__ctz_;
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
__m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __result.__ctz_);
*__result.__seg_ &= ~__m;
if (__result.__ctz_ > __first.__ctz_)
*__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
else
*__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
__dn -= __ddn;
if (__dn > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __dn);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
__result.__ctz_ = static_cast<unsigned>(__dn);
}
++__first.__seg_;
// __first.__ctz_ = 0;
}
// __first.__ctz_ == 0;
// do middle words
unsigned __clz_r = __bits_per_word - __result.__ctz_;
__storage_type __m = std::__leading_mask<__storage_type>(__result.__ctz_);
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
__storage_type __b = *__first.__seg_;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b << __result.__ctz_;
++__result.__seg_;
*__result.__seg_ &= __m;
*__result.__seg_ |= __b >> __clz_r;
}
// do last word
if (__n > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
__storage_type __b = *__first.__seg_ & __m;
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
__m = std::__middle_mask<__storage_type>(__clz_r - __dn, __result.__ctz_);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b << __result.__ctz_;
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
__n -= __dn;
if (__n > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b >> __dn;
__result.__ctz_ = static_cast<unsigned>(__n);
}
}
}
return __result;
}
struct __copy_impl { struct __copy_impl {
template <class _InIter, class _Sent, class _OutIter> template <class _InIter,
class _Sent,
class _OutIter,
__enable_if_t<!__specialized_algorithm<_Algorithm::__copy,
__iterator_pair<_InIter, _Sent>,
__single_iterator<_OutIter> >::__has_algorithm,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _Sent __last, _OutIter __result) const { operator()(_InIter __first, _Sent __last, _OutIter __result) const {
while (__first != __last) { while (__first != __last) {
@@ -167,37 +56,39 @@ struct __copy_impl {
return std::make_pair(std::move(__first), std::move(__result)); return std::make_pair(std::move(__first), std::move(__result));
} }
template <class _InIter, class _OutIter> template <class _InIter,
struct _CopySegment { class _Sent,
using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>; class _OutIter,
__enable_if_t<__specialized_algorithm<_Algorithm::__copy,
__iterator_pair<_InIter, _Sent>,
__single_iterator<_OutIter> >::__has_algorithm,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static pair<_InIter, _OutIter>
operator()(_InIter __first, _Sent __last, _OutIter __result) {
return __specialized_algorithm<_Algorithm::__copy, __iterator_pair<_InIter, _Sent>, __single_iterator<_OutIter> >()(
std::move(__first), std::move(__last), std::move(__result));
}
_OutIter& __result_; template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _CopySegment(_OutIter& __result)
: __result_(__result) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
__result_ = std::__copy(__lfirst, __llast, std::move(__result_)).second;
}
};
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
std::__for_each_segment(__first, __last, _CopySegment<_InIter, _OutIter>(__result)); using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
std::__for_each_segment(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
__result = std::__copy(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
});
return std::make_pair(__last, std::move(__result)); return std::make_pair(__last, std::move(__result));
} }
template <class _InIter, template <class _InIter,
class _OutIter, class _OutIter,
__enable_if_t<__has_random_access_iterator_category<_InIter>::value && __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
!__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>,
int> = 0> int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_OutIter>; using _Traits = __segmented_iterator_traits<_OutIter>;
using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; using _DiffT =
typename common_type<__iterator_difference_type<_InIter>, __iterator_difference_type<_OutIter> >::type;
if (__first == __last) if (__first == __last)
return std::make_pair(std::move(__first), std::move(__result)); return std::make_pair(std::move(__first), std::move(__result));
@@ -217,16 +108,6 @@ struct __copy_impl {
} }
} }
template <class _Cp, bool _IsConst>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
operator()(__bit_iterator<_Cp, _IsConst> __first,
__bit_iterator<_Cp, _IsConst> __last,
__bit_iterator<_Cp, false> __result) const {
if (__first.__ctz_ == __result.__ctz_)
return std::make_pair(__last, std::__copy_aligned(__first, __last, __result));
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
}
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+9 -24
View File
@@ -11,6 +11,7 @@
#include <__algorithm/copy_move_common.h> #include <__algorithm/copy_move_common.h>
#include <__algorithm/copy_n.h> #include <__algorithm/copy_n.h>
#include <__algorithm/for_each_segment.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h> #include <__algorithm/min.h>
#include <__config> #include <__config>
@@ -170,37 +171,20 @@ struct __copy_backward_impl {
return std::make_pair(std::move(__original_last_iter), std::move(__result)); return std::make_pair(std::move(__original_last_iter), std::move(__result));
} }
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_InIter>; using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
auto __sfirst = _Traits::__segment(__first); std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
auto __slast = _Traits::__segment(__last); __result = std::__copy_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
if (__sfirst == __slast) { });
auto __iters =
std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
return std::make_pair(__last, __iters.second);
}
__result =
std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
.second;
--__slast;
while (__sfirst != __slast) {
__result =
std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
.second;
--__slast;
}
__result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
.second;
return std::make_pair(__last, std::move(__result)); return std::make_pair(__last, std::move(__result));
} }
template <class _InIter, template <class _InIter,
class _OutIter, class _OutIter,
__enable_if_t<__has_random_access_iterator_category<_InIter>::value && __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
!__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>,
int> = 0> int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
@@ -214,7 +198,8 @@ struct __copy_backward_impl {
auto __local_last = _Traits::__local(__result); auto __local_last = _Traits::__local(__result);
while (true) { while (true) {
using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; using _DiffT =
typename common_type<__iterator_difference_type<_InIter>, __iterator_difference_type<_OutIter> >::type;
auto __local_first = _Traits::__begin(__segment_iterator); auto __local_first = _Traits::__begin(__segment_iterator);
auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
+50 -16
View File
@@ -10,31 +10,63 @@
#define _LIBCPP___ALGORITHM_COPY_N_H #define _LIBCPP___ALGORITHM_COPY_N_H
#include <__algorithm/copy.h> #include <__algorithm/copy.h>
#include <__algorithm/iterator_operations.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__utility/convert_to_integral.h> #include <__utility/convert_to_integral.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy,
class _InIter,
class _OutIter,
__enable_if_t<__has_random_access_iterator_category<_InIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
__copy_n(_InIter __first, typename _IterOps<_AlgPolicy>::template __difference_type<_InIter> __n, _OutIter __result) {
return std::__copy(__first, __first + __n, std::move(__result));
}
template <class _AlgPolicy,
class _InIter,
class _OutIter,
__enable_if_t<!__has_random_access_iterator_category<_InIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
__copy_n(_InIter __first, typename _IterOps<_AlgPolicy>::template __difference_type<_InIter> __n, _OutIter __result) {
while (__n != 0) {
*__result = *__first;
++__first;
++__result;
--__n;
}
return std::make_pair(std::move(__first), std::move(__result));
}
// The InputIterator case is handled specially here because it's been written in a way to avoid incrementing __first
// if not absolutely required. This was done to allow its use with istream_iterator and we want to avoid breaking
// people, at least currently.
// See https://github.com/llvm/llvm-project/commit/99847d2bf132854fffa019bab19818768102ccad
template <class _InputIterator, template <class _InputIterator,
class _Size, class _Size,
class _OutputIterator, class _OutputIterator,
__enable_if_t<__has_input_iterator_category<_InputIterator>::value && __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
!__has_random_access_iterator_category<_InputIterator>::value, _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
int> = 0> copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) {
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator using _IntegralSize = decltype(std::__convert_to_integral(__n));
copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) { _IntegralSize __converted = __n;
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; if (__converted > 0) {
_IntegralSize __n = __orig_n;
if (__n > 0) {
*__result = *__first; *__result = *__first;
++__result; ++__result;
for (--__n; __n > 0; --__n) { for (--__converted; __converted > 0; --__converted) {
++__first; ++__first;
*__result = *__first; *__result = *__first;
++__result; ++__result;
@@ -46,15 +78,17 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
template <class _InputIterator, template <class _InputIterator,
class _Size, class _Size,
class _OutputIterator, class _OutputIterator,
__enable_if_t<__has_random_access_iterator_category<_InputIterator>::value, int> = 0> __enable_if_t<!__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) { copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) {
typedef typename iterator_traits<_InputIterator>::difference_type difference_type; using _IntegralSize = decltype(std::__convert_to_integral(__n));
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; _IntegralSize __converted = __n;
_IntegralSize __n = __orig_n; return std::__copy_n<_ClassicAlgPolicy>(__first, __iterator_difference_type<_InputIterator>(__converted), __result)
return std::copy(__first, __first + difference_type(__n), __result); .second;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_COPY_N_H #endif // _LIBCPP___ALGORITHM_COPY_N_H
+2 -2
View File
@@ -72,7 +72,7 @@ __count_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_t
} }
template <class, class _Cp, bool _IsConst, class _Tp, class _Proj, __enable_if_t<__is_identity<_Proj>::value, int> = 0> template <class, class _Cp, bool _IsConst, class _Tp, class _Proj, __enable_if_t<__is_identity<_Proj>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<__bit_iterator<_Cp, _IsConst> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iterator_difference_type<__bit_iterator<_Cp, _IsConst> >
__count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) { __count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) {
if (__value) if (__value)
return std::__count_bool<true>( return std::__count_bool<true>(
@@ -82,7 +82,7 @@ __count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __l
} }
template <class _InputIterator, class _Tp> template <class _InputIterator, class _Tp>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iterator_difference_type<_InputIterator>
count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { count(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
__identity __proj; __identity __proj;
return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj); return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj);
+43 -55
View File
@@ -160,22 +160,28 @@ template <class _Cp,
bool _IsConst1, bool _IsConst1,
bool _IsConst2, bool _IsConst2,
class _BinaryPredicate, class _BinaryPredicate,
__enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>, int> = 0> class _Proj1,
class _Proj2,
__enable_if_t<__is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>,
int> = 0>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl(
__bit_iterator<_Cp, _IsConst1> __first1, __bit_iterator<_Cp, _IsConst1> __first1,
__bit_iterator<_Cp, _IsConst1> __last1, __bit_iterator<_Cp, _IsConst1> __last1,
__bit_iterator<_Cp, _IsConst2> __first2, __bit_iterator<_Cp, _IsConst2> __first2,
_BinaryPredicate) { _BinaryPredicate,
_Proj1&,
_Proj2&) {
if (__first1.__ctz_ == __first2.__ctz_) if (__first1.__ctz_ == __first2.__ctz_)
return std::__equal_aligned(__first1, __last1, __first2); return std::__equal_aligned(__first1, __last1, __first2);
return std::__equal_unaligned(__first1, __last1, __first2); return std::__equal_unaligned(__first1, __last1, __first2);
} }
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InIter1, class _Sent1, class _InIter2, class _Pred, class _Proj1, class _Proj2>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl(
_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) { _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
for (; __first1 != __last1; ++__first1, (void)++__first2) for (; __first1 != __last1; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2)) if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
return false; return false;
return true; return true;
} }
@@ -183,19 +189,23 @@ template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
template <class _Tp, template <class _Tp,
class _Up, class _Up,
class _BinaryPredicate, class _BinaryPredicate,
__enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, _Tp, _Up> && !is_volatile<_Tp>::value && class _Proj1,
!is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, class _Proj2,
__enable_if_t<__is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
__desugars_to_v<__equal_tag, _BinaryPredicate, _Tp, _Up> && !is_volatile<_Tp>::value &&
!is_volatile<_Up>::value && __is_trivially_equality_comparable_v<_Tp, _Up>,
int> = 0> int> = 0>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) { __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&, _Proj1&, _Proj2&) {
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
} }
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
__identity __proj;
return std::__equal_iter_impl( return std::__equal_iter_impl(
std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred, __proj, __proj);
} }
template <class _InputIterator1, class _InputIterator2> template <class _InputIterator1, class _InputIterator2>
@@ -206,52 +216,28 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> template <bool __known_equal_length,
class _Iter1,
class _Sent1,
class _Iter2,
class _Sent2,
class _Pred,
class _Proj1,
class _Proj2>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) { _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) {
while (__first1 != __last1 && __first2 != __last2) { if constexpr (__known_equal_length) {
if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) return std::__equal_iter_impl(
return false; std::move(__first1), std::move(__last1), std::move(__first2), __comp, __proj1, __proj2);
++__first1; } else {
++__first2; while (__first1 != __last1 && __first2 != __last2) {
if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
return false;
++__first1;
++__first2;
}
return __first1 == __last1 && __first2 == __last2;
} }
return __first1 == __last1 && __first2 == __last2;
}
template <class _Tp,
class _Up,
class _Pred,
class _Proj1,
class _Proj2,
__enable_if_t<__desugars_to_v<__equal_tag, _Pred, _Tp, _Up> && __is_identity<_Proj1>::value &&
__is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value &&
__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
int> = 0>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
}
template <class _Cp,
bool _IsConst1,
bool _IsConst2,
class _Pred,
class _Proj1,
class _Proj2,
__enable_if_t<__desugars_to_v<__equal_tag, _Pred, bool, bool> && __is_identity<_Proj1>::value &&
__is_identity<_Proj2>::value,
int> = 0>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
__bit_iterator<_Cp, _IsConst1> __first1,
__bit_iterator<_Cp, _IsConst1> __last1,
__bit_iterator<_Cp, _IsConst2> __first2,
__bit_iterator<_Cp, _IsConst2>,
_Pred&,
_Proj1&,
_Proj2&) {
if (__first1.__ctz_ == __first2.__ctz_)
return std::__equal_aligned(__first1, __last1, __first2);
return std::__equal_unaligned(__first1, __last1, __first2);
} }
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
@@ -261,13 +247,15 @@ equal(_InputIterator1 __first1,
_InputIterator2 __first2, _InputIterator2 __first2,
_InputIterator2 __last2, _InputIterator2 __last2,
_BinaryPredicate __pred) { _BinaryPredicate __pred) {
if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && static constexpr bool __both_random_access =
__has_random_access_iterator_category<_InputIterator2>::value) { __has_random_access_iterator_category<_InputIterator1>::value &&
__has_random_access_iterator_category<_InputIterator2>::value;
if constexpr (__both_random_access) {
if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
return false; return false;
} }
__identity __proj; __identity __proj;
return std::__equal_impl( return std::__equal_impl<__both_random_access>(
std::__unwrap_iter(__first1), std::__unwrap_iter(__first1),
std::__unwrap_iter(__last1), std::__unwrap_iter(__last1),
std::__unwrap_iter(__first2), std::__unwrap_iter(__first2),
+26 -8
View File
@@ -10,8 +10,12 @@
#define _LIBCPP___ALGORITHM_FILL_H #define _LIBCPP___ALGORITHM_FILL_H
#include <__algorithm/fill_n.h> #include <__algorithm/fill_n.h>
#include <__algorithm/for_each_segment.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -21,23 +25,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. // fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Sentinel, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag) { __fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __value) {
#ifndef _LIBCPP_CXX03_LANG
if constexpr (is_same<_ForwardIterator, _Sentinel>::value && __is_segmented_iterator_v<_ForwardIterator>) {
using __local_iterator_t = typename __segmented_iterator_traits<_ForwardIterator>::__local_iterator;
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
std::__fill(__lfirst, __llast, __value);
});
return __last;
}
#endif
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
*__first = __value; *__first = __value;
return __first;
} }
template <class _RandomAccessIterator, class _Tp> template <class _RandomAccessIterator,
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void class _Tp,
__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag) { __enable_if_t<__has_random_access_iterator_category<_RandomAccessIterator>::value &&
std::fill_n(__first, __last - __first, __value); !__is_segmented_iterator_v<_RandomAccessIterator>,
int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value) {
return std::__fill_n(__first, __last - __first, __value);
} }
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
std::__fill(__first, __last, __value, typename iterator_traits<_ForwardIterator>::iterator_category()); std::__fill(__first, __last, __value);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+32 -46
View File
@@ -9,11 +9,14 @@
#ifndef _LIBCPP___ALGORITHM_FILL_N_H #ifndef _LIBCPP___ALGORITHM_FILL_N_H
#define _LIBCPP___ALGORITHM_FILL_N_H #define _LIBCPP___ALGORITHM_FILL_N_H
#include <__algorithm/min.h> #include <__algorithm/for_each_n_segment.h>
#include <__algorithm/specialized_algorithms.h>
#include <__config> #include <__config>
#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h>
#include <__memory/pointer_traits.h> #include <__iterator/segmented_iterator.h>
#include <__type_traits/enable_if.h>
#include <__utility/convert_to_integral.h> #include <__utility/convert_to_integral.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -26,56 +29,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. // fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
template <class _OutputIterator, class _Size, class _Tp> template <
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator class _OutputIterator,
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value); class _Size,
class _Tp,
template <bool _FillVal, class _Cp> __enable_if_t<!__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutputIterator> >::__has_algorithm,
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void int> = 0>
__fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {
using _It = __bit_iterator<_Cp, false>;
using __storage_type = typename _It::__storage_type;
const int __bits_per_word = _It::__bits_per_word;
// do first partial word
if (__first.__ctz_ != 0) {
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
__storage_type __dn = std::min(__clz_f, __n);
std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
__n -= __dn;
++__first.__seg_;
}
// do middle whole words
__storage_type __nw = __n / __bits_per_word;
std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
__n -= __nw * __bits_per_word;
// do last partial word
if (__n > 0) {
__first.__seg_ += __nw;
std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
}
}
template <class _Cp, class _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
__fill_n(__bit_iterator<_Cp, false> __first, _Size __n, const bool& __value) {
if (__n > 0) {
if (__value)
std::__fill_n_bool<true>(__first, __n);
else
std::__fill_n_bool<false>(__first, __n);
}
return __first + __n;
}
template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) { __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
#ifndef _LIBCPP_CXX03_LANG
if constexpr (__is_segmented_iterator_v<_OutputIterator>) {
using __local_iterator = typename __segmented_iterator_traits<_OutputIterator>::__local_iterator;
if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
return std::__for_each_n_segment(__first, __n, [&](__local_iterator __lfirst, __local_iterator __llast) {
std::__fill_n(__lfirst, __llast - __lfirst, __value);
});
}
}
#endif
for (; __n > 0; ++__first, (void)--__n) for (; __n > 0; ++__first, (void)--__n)
*__first = __value; *__first = __value;
return __first; return __first;
} }
template <class _OutIter,
class _Size,
class _Tp,
__enable_if_t<__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >::__has_algorithm,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutIter __fill_n(_OutIter __first, _Size __n, const _Tp& __value) {
return __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >()(
std::move(__first), __n, __value);
}
template <class _OutputIterator, class _Size, class _Tp> template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) { fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
+97 -40
View File
@@ -12,16 +12,19 @@
#include <__algorithm/find_segment_if.h> #include <__algorithm/find_segment_if.h>
#include <__algorithm/min.h> #include <__algorithm/min.h>
#include <__algorithm/simd_utils.h>
#include <__algorithm/unwrap_iter.h> #include <__algorithm/unwrap_iter.h>
#include <__bit/countr.h> #include <__bit/countr.h>
#include <__bit/invert_if.h> #include <__bit/invert_if.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__fwd/bit_reference.h> #include <__fwd/bit_reference.h>
#include <__iterator/segmented_iterator.h> #include <__iterator/segmented_iterator.h>
#include <__string/constexpr_c_functions.h> #include <__string/constexpr_c_functions.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_equality_comparable.h> #include <__type_traits/is_equality_comparable.h>
#include <__type_traits/is_integral.h> #include <__type_traits/is_integral.h>
#include <__type_traits/is_signed.h> #include <__type_traits/is_signed.h>
@@ -44,46 +47,108 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// generic implementation // generic implementation
template <class _Iter, class _Sent, class _Tp, class _Proj> template <class _Iter, class _Sent, class _Tp, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
__find(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { __find_loop(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (std::__invoke(__proj, *__first) == __value) if (std::__invoke(__proj, *__first) == __value)
break; break;
return __first; return __first;
} }
template <class _Iter, class _Sent, class _Tp, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
__find(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
return std::__find_loop(std::move(__first), std::move(__last), __value, __proj);
}
#if _LIBCPP_VECTORIZE_ALGORITHMS
template <class _Tp, class _Up>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find_vectorized(_Tp* __first, _Tp* __last, _Up __value) {
if (!__libcpp_is_constant_evaluated()) {
constexpr size_t __unroll_count = 4;
constexpr size_t __vec_size = __native_vector_size<_Tp>;
using __vec = __simd_vector<_Tp, __vec_size>;
auto __orig_first = __first;
auto __values = static_cast<__simd_vector<_Tp, __vec_size>>(__value); // broadcast the value
while (static_cast<size_t>(__last - __first) >= __unroll_count * __vec_size) [[__unlikely__]] {
__vec __lhs[__unroll_count];
for (size_t __i = 0; __i != __unroll_count; ++__i)
__lhs[__i] = std::__load_vector<__vec>(__first + __i * __vec_size);
for (size_t __i = 0; __i != __unroll_count; ++__i) {
if (auto __cmp_res = __lhs[__i] == __values; std::__any_of(__cmp_res)) {
auto __offset = __i * __vec_size + std::__find_first_set(__cmp_res);
return __first + __offset;
}
}
__first += __unroll_count * __vec_size;
}
// check the remaining 0-3 vectors
while (static_cast<size_t>(__last - __first) >= __vec_size) {
if (auto __cmp_res = std::__load_vector<__vec>(__first) == __values; std::__any_of(__cmp_res)) {
return __first + std::__find_first_set(__cmp_res);
}
__first += __vec_size;
}
if (__last - __first == 0)
return __first;
// Check if we can load elements in front of the current pointer. If that's the case load a vector at
// (last - vector_size) to check the remaining elements
if (static_cast<size_t>(__first - __orig_first) >= __vec_size) {
__first = __last - __vec_size;
return __first + std::__find_first_set(std::__load_vector<__vec>(__first) == __values);
}
}
__identity __proj;
return std::__find_loop(__first, __last, __value, __proj);
}
#endif
#ifndef _LIBCPP_CXX03_LANG
// trivially equality comparable implementations // trivially equality comparable implementations
template <class _Tp, template <class _Tp,
class _Up, class _Up,
class _Proj, class _Proj,
__enable_if_t<__is_identity<_Proj>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && __enable_if_t<__is_identity<_Proj>::value && __is_trivially_equality_comparable_v<_Tp, _Up>, int> = 0>
sizeof(_Tp) == 1,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) {
if (auto __ret = std::__constexpr_memchr(__first, __value, __last - __first)) if constexpr (sizeof(_Tp) == 1) {
return __ret; if (auto __ret = std::__constexpr_memchr(__first, __value, __last - __first))
return __last; return __ret;
return __last;
}
# if _LIBCPP_HAS_WIDE_CHARACTERS
else if constexpr (sizeof(_Tp) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t)) {
if (auto __ret = std::__constexpr_wmemchr(__first, __value, __last - __first))
return __ret;
return __last;
}
# endif
# if _LIBCPP_VECTORIZE_ALGORITHMS
else if constexpr (is_integral<_Tp>::value) {
return std::__find_vectorized(__first, __last, __value);
}
# endif
else {
__identity __proj;
return std::__find_loop(__first, __last, __value, __proj);
}
} }
#endif
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <class _Tp,
class _Up,
class _Proj,
__enable_if_t<__is_identity<_Proj>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value &&
sizeof(_Tp) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t),
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) {
if (auto __ret = std::__constexpr_wmemchr(__first, __value, __last - __first))
return __ret;
return __last;
}
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
// TODO: This should also be possible to get right with different signedness // TODO: This should also be possible to get right with different signedness
// cast integral types to allow vectorization // cast integral types to allow vectorization
template <class _Tp, template <class _Tp,
class _Up, class _Up,
class _Proj, class _Proj,
__enable_if_t<__is_identity<_Proj>::value && !__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && __enable_if_t<__is_identity<_Proj>::value && !__is_trivially_equality_comparable_v<_Tp, _Up> &&
is_integral<_Tp>::value && is_integral<_Up>::value && is_integral<_Tp>::value && is_integral<_Up>::value &&
is_signed<_Tp>::value == is_signed<_Up>::value, is_signed<_Tp>::value == is_signed<_Up>::value,
int> = 0> int> = 0>
@@ -143,31 +208,23 @@ __find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __la
// segmented iterator implementation // segmented iterator implementation
template <class>
struct __find_segment;
template <class _SegmentedIterator, template <class _SegmentedIterator,
class _Tp, class _Tp,
class _Proj, class _Proj,
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0> __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__find(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) { __find(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) {
return std::__find_segment_if(std::move(__first), std::move(__last), __find_segment<_Tp>(__value), __proj); using __local_iterator = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
return std::__find_segment_if(
std::move(__first),
std::move(__last),
[&__value](__local_iterator __lfirst, __local_iterator __llast, _Proj& __lproj) {
return std::__rewrap_iter(
__lfirst, std::__find(std::__unwrap_iter(__lfirst), std::__unwrap_iter(__llast), __value, __lproj));
},
__proj);
} }
template <class _Tp>
struct __find_segment {
const _Tp& __value_;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __find_segment(const _Tp& __value) : __value_(__value) {}
template <class _InputIterator, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _InputIterator
operator()(_InputIterator __first, _InputIterator __last, _Proj& __proj) const {
return std::__find(__first, __last, __value_, __proj);
}
};
// public API // public API
template <class _InputIterator, class _Tp> template <class _InputIterator, class _Tp>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
+105
View File
@@ -76,6 +76,111 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
} }
} }
template <class _AlgPolicy,
class _Pred,
class _Iter1,
class _Sent1,
class _Iter2,
class _Sent2,
class _Proj1,
class _Proj2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter1> __find_end_impl(
_Iter1 __first1,
_Sent1 __sent1,
_Iter2 __first2,
_Sent2 __sent2,
_Pred& __pred,
_Proj1& __proj1,
_Proj2& __proj2,
bidirectional_iterator_tag,
bidirectional_iterator_tag) {
auto __last1 = _IterOps<_AlgPolicy>::next(__first1, __sent1);
auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __sent2);
// modeled after search algorithm (in reverse)
if (__first2 == __last2)
return std::make_pair(__last1, __last1); // Everything matches an empty sequence
_Iter1 __l1 = __last1;
_Iter2 __l2 = __last2;
--__l2;
while (true) {
// Find last element in sequence 1 that matches *(__last2-1), with a mininum of loop checks
while (true) {
if (__first1 == __l1) // return __last1 if no element matches *__first2
return std::make_pair(__last1, __last1);
if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))
break;
}
// *__l1 matches *__l2, now match elements before here
_Iter1 __match_last = __l1;
_Iter1 __m1 = __l1;
_Iter2 __m2 = __l2;
while (true) {
if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern)
return std::make_pair(__m1, ++__match_last);
if (__m1 == __first1) // Otherwise if source exhaused, pattern not found
return std::make_pair(__last1, __last1);
// if there is a mismatch, restart with a new __l1
if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) {
break;
} // else there is a match, check next elements
}
}
}
template <class _AlgPolicy,
class _Pred,
class _Iter1,
class _Sent1,
class _Iter2,
class _Sent2,
class _Proj1,
class _Proj2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(
_Iter1 __first1,
_Sent1 __sent1,
_Iter2 __first2,
_Sent2 __sent2,
_Pred& __pred,
_Proj1& __proj1,
_Proj2& __proj2,
random_access_iterator_tag,
random_access_iterator_tag) {
typedef typename iterator_traits<_Iter1>::difference_type _D1;
auto __last1 = _IterOps<_AlgPolicy>::next(__first1, __sent1);
auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __sent2);
// Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern
auto __len2 = __last2 - __first2;
if (__len2 == 0)
return std::make_pair(__last1, __last1);
auto __len1 = __last1 - __first1;
if (__len1 < __len2)
return std::make_pair(__last1, __last1);
const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here
_Iter1 __l1 = __last1;
_Iter2 __l2 = __last2;
--__l2;
while (true) {
while (true) {
if (__s == __l1)
return std::make_pair(__last1, __last1);
if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))
break;
}
_Iter1 __last_match = __l1;
_Iter1 __m1 = __l1;
_Iter2 __m2 = __l2;
while (true) {
if (__m2 == __first2)
return std::make_pair(__m1, ++__last_match);
// no need to check range on __m1 because __s guarantees we have enough source
if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) {
break;
}
}
}
}
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic( [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic(
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
+18 -24
View File
@@ -11,45 +11,41 @@
#define _LIBCPP___ALGORITHM_FOR_EACH_H #define _LIBCPP___ALGORITHM_FOR_EACH_H
#include <__algorithm/for_each_segment.h> #include <__algorithm/for_each_segment.h>
#include <__algorithm/specialized_algorithms.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__iterator/segmented_iterator.h> #include <__iterator/segmented_iterator.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__utility/move.h> #include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Sent, class _Func, class _Proj> template <class _InputIterator, class _Sent, class _Func, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) { __for_each(_InputIterator __first, _Sent __last, _Func& __func, _Proj& __proj) {
#ifndef _LIBCPP_CXX03_LANG
if constexpr (using _SpecialAlg =
__specialized_algorithm<_Algorithm::__for_each, __iterator_pair<_InputIterator, _Sent>>;
_SpecialAlg::__has_algorithm) {
_SpecialAlg()(__first, __last, __func, __proj);
return __last;
} else if constexpr (is_same<_InputIterator, _Sent>::value && __is_segmented_iterator_v<_InputIterator>) {
using __local_iterator_t = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
std::__for_each(__lfirst, __llast, __func, __proj);
});
return __last;
}
#endif
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
std::__invoke(__f, std::__invoke(__proj, *__first)); std::__invoke(__func, std::__invoke(__proj, *__first));
return __first; return __first;
} }
#ifndef _LIBCPP_CXX03_LANG
template <class _SegmentedIterator,
class _Func,
class _Proj,
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) {
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
std::__for_each(__lfirst, __llast, __func, __proj);
});
return __last;
}
#endif // !_LIBCPP_CXX03_LANG
template <class _InputIterator, class _Func> template <class _InputIterator, class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func
for_each(_InputIterator __first, _InputIterator __last, _Func __f) { for_each(_InputIterator __first, _InputIterator __last, _Func __f) {
@@ -60,6 +56,4 @@ for_each(_InputIterator __first, _InputIterator __last, _Func __f) {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_FOR_EACH_H #endif // _LIBCPP___ALGORITHM_FOR_EACH_H
+20 -47
View File
@@ -16,10 +16,7 @@
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__iterator/segmented_iterator.h> #include <__iterator/segmented_iterator.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__type_traits/negation.h>
#include <__utility/convert_to_integral.h> #include <__utility/convert_to_integral.h>
#include <__utility/move.h> #include <__utility/move.h>
@@ -32,57 +29,33 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, template <class _InputIterator, class _Size, class _Func, class _Proj>
class _Size,
class _Func,
class _Proj,
__enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
_Or< _Not<__is_segmented_iterator<_InputIterator> >,
_Not<__has_random_access_local_iterator<_InputIterator> > >::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { __for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
_IntegralSize __n = __orig_n; _IntegralSize __n = __orig_n;
while (__n > 0) {
std::__invoke(__f, std::__invoke(__proj, *__first));
++__first;
--__n;
}
return std::move(__first);
}
template <class _RandIter,
class _Size,
class _Func,
class _Proj,
__enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter
__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n;
auto __last = __first + __n;
std::__for_each(__first, __last, __f, __proj);
return __last;
}
#ifndef _LIBCPP_CXX03_LANG #ifndef _LIBCPP_CXX03_LANG
template <class _SegmentedIterator, if constexpr (__is_segmented_iterator_v<_InputIterator>) {
class _Size, using __local_iterator = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
class _Func, if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
class _Proj, return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator __lfirst, __local_iterator __llast) {
__enable_if_t<!__has_random_access_iterator_category<_SegmentedIterator>::value && std::__for_each(__lfirst, __llast, __f, __proj);
__is_segmented_iterator<_SegmentedIterator>::value && });
__has_random_access_iterator_category< } else {
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, return std::__for_each(__first, __first + __n, __f, __proj);
int> = 0> }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator } else
__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) { #endif
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator; {
return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) { while (__n > 0) {
std::__for_each(__lfirst, __llast, __f, __proj); std::__invoke(__f, std::__invoke(__proj, *__first));
}); ++__first;
--__n;
}
return std::move(__first);
}
} }
#endif // !_LIBCPP_CXX03_LANG
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
+1 -1
View File
@@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _SegmentedIterator, class _Size, class _Functor> template <class _SegmentedIterator, class _Size, class _Functor>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) { __for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) {
static_assert(__is_segmented_iterator<_SegmentedIterator>::value && static_assert(__is_segmented_iterator_v<_SegmentedIterator> &&
__has_random_access_iterator_category< __has_random_access_iterator_category<
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value, typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
"__for_each_n_segment only works with segmented iterators with random-access local iterators"); "__for_each_n_segment only works with segmented iterators with random-access local iterators");
+26
View File
@@ -48,6 +48,32 @@ __for_each_segment(_SegmentedIterator __first, _SegmentedIterator __last, _Funct
__func(_Traits::__begin(__sfirst), _Traits::__local(__last)); __func(_Traits::__begin(__sfirst), _Traits::__local(__last));
} }
template <class _SegmentedIterator, class _Functor>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__for_each_segment_backward(_SegmentedIterator __first, _SegmentedIterator __last, _Functor __func) {
using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
auto __sfirst = _Traits::__segment(__first);
auto __slast = _Traits::__segment(__last);
// We are in a single segment, so we might not be at the beginning or end
if (__sfirst == __slast) {
__func(_Traits::__local(__first), _Traits::__local(__last));
return;
}
// We have more than one segment. Iterate over the last segment, since we might not start at the end
__func(_Traits::__begin(__slast), _Traits::__local(__last));
--__slast;
// iterate over the segments which are guaranteed to be completely in the range
while (__sfirst != __slast) {
__func(_Traits::__begin(__slast), _Traits::__end(__slast));
--__slast;
}
// iterate over the first segment
__func(_Traits::__local(__first), _Traits::__end(__slast));
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H #endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H
+4 -2
View File
@@ -9,7 +9,9 @@
#ifndef _LIBCPP___ALGORITHM_GENERATE_H #ifndef _LIBCPP___ALGORITHM_GENERATE_H
#define _LIBCPP___ALGORITHM_GENERATE_H #define _LIBCPP___ALGORITHM_GENERATE_H
#include <__algorithm/for_each.h>
#include <__config> #include <__config>
#include <__utility/forward.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -20,8 +22,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Generator> template <class _ForwardIterator, class _Generator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
for (; __first != __last; ++__first) using __iter_ref = decltype(*__first);
*__first = __gen(); std::for_each(__first, __last, [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); });
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+19 -6
View File
@@ -9,25 +9,38 @@
#ifndef _LIBCPP___ALGORITHM_GENERATE_N_H #ifndef _LIBCPP___ALGORITHM_GENERATE_N_H
#define _LIBCPP___ALGORITHM_GENERATE_N_H #define _LIBCPP___ALGORITHM_GENERATE_N_H
#include <__algorithm/for_each_n.h>
#include <__config> #include <__config>
#include <__utility/convert_to_integral.h> #include <__functional/identity.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _OutputIterator, class _Size, class _Generator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
__generate_n(_OutputIterator __first, _Size __orig_n, _Generator& __gen) {
using __iter_ref = decltype(*__first);
__identity __proj;
auto __f = [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); };
return std::__for_each_n(std::move(__first), __orig_n, __f, __proj);
}
template <class _OutputIterator, class _Size, class _Generator> template <class _OutputIterator, class _Size, class _Generator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) { generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) {
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize; return std::__generate_n(std::move(__first), __orig_n, __gen);
_IntegralSize __n = __orig_n;
for (; __n > 0; ++__first, (void)--__n)
*__first = __gen();
return __first;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_GENERATE_N_H #endif // _LIBCPP___ALGORITHM_GENERATE_N_H
+4 -4
View File
@@ -78,7 +78,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl(
_Pred&& __pred, _Pred&& __pred,
_Proj1&& __proj1, _Proj1&& __proj1,
_Proj2&& __proj2) { _Proj2&& __proj2) {
using _D1 = __iter_diff_t<_Iter1>; using _D1 = __iterator_difference_type<_Iter1>;
for (auto __i = __first1; __i != __last1; ++__i) { for (auto __i = __first1; __i != __last1; ++__i) {
// Have we already counted the number of *__i in [f1, l1)? // Have we already counted the number of *__i in [f1, l1)?
@@ -126,7 +126,7 @@ template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _Fo
return true; return true;
// __first1 != __last1 && *__first1 != *__first2 // __first1 != __last1 && *__first1 != *__first2
using _D1 = __iter_diff_t<_ForwardIterator1>; using _D1 = __iterator_difference_type<_ForwardIterator1>;
_D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
if (__l1 == _D1(1)) if (__l1 == _D1(1))
return false; return false;
@@ -173,10 +173,10 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
if (__first2 == __last2) // Second range is shorter if (__first2 == __last2) // Second range is shorter
return false; return false;
using _D1 = __iter_diff_t<_Iter1>; using _D1 = __iterator_difference_type<_Iter1>;
_D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
using _D2 = __iter_diff_t<_Iter2>; using _D2 = __iterator_difference_type<_Iter2>;
_D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2);
if (__l1 != __l2) if (__l1 != __l2)
return false; return false;
+3
View File
@@ -219,6 +219,9 @@ private:
template <class _AlgPolicy, class _Iter> template <class _AlgPolicy, class _Iter>
using __policy_iter_diff_t _LIBCPP_NODEBUG = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>; using __policy_iter_diff_t _LIBCPP_NODEBUG = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>;
template <class _AlgPolicy, class _Iter>
using __policy_value_type _LIBCPP_NODEBUG = typename _IterOps<_AlgPolicy>::template __value_type<_Iter>;
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS _LIBCPP_POP_MACROS
+2 -2
View File
@@ -66,8 +66,8 @@ template <class _Tp,
class _Proj2, class _Proj2,
class _Comp, class _Comp,
__enable_if_t<__desugars_to_v<__totally_ordered_less_tag, _Comp, _Tp, _Tp> && !is_volatile<_Tp>::value && __enable_if_t<__desugars_to_v<__totally_ordered_less_tag, _Comp, _Tp, _Tp> && !is_volatile<_Tp>::value &&
__libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value && __is_trivially_equality_comparable_v<_Tp, _Tp> && __is_identity<_Proj1>::value &&
__is_identity<_Proj1>::value && __is_identity<_Proj2>::value, __is_identity<_Proj2>::value,
int> = 0> int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__lexicographical_compare(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Comp&, _Proj1&, _Proj2&) { __lexicographical_compare(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Comp&, _Proj1&, _Proj2&) {
@@ -37,13 +37,13 @@ template <class _InputIterator1, class _InputIterator2, class _Cmp>
_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_path( _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_path(
_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp)
-> decltype(__comp(*__first1, *__first2)) { -> decltype(__comp(*__first1, *__first2)) {
static_assert( static_assert(signed_integral<__iterator_difference_type<_InputIterator1>>,
signed_integral<__iter_diff_t<_InputIterator1>>, "Using a non-integral difference_type is undefined behavior."); "Using a non-integral difference_type is undefined behavior.");
static_assert( static_assert(signed_integral<__iterator_difference_type<_InputIterator2>>,
signed_integral<__iter_diff_t<_InputIterator2>>, "Using a non-integral difference_type is undefined behavior."); "Using a non-integral difference_type is undefined behavior.");
using _Len1 = __iter_diff_t<_InputIterator1>; using _Len1 = __iterator_difference_type<_InputIterator1>;
using _Len2 = __iter_diff_t<_InputIterator2>; using _Len2 = __iterator_difference_type<_InputIterator2>;
using _Common = common_type_t<_Len1, _Len2>; using _Common = common_type_t<_Len1, _Len2>;
_Len1 __len1 = __last1 - __first1; _Len1 __len1 = __last1 - __first1;
+16 -4
View File
@@ -12,9 +12,11 @@
#include <__algorithm/comp.h> #include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h> #include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/push_heap.h>
#include <__algorithm/sift_down.h> #include <__algorithm/sift_down.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__type_traits/is_arithmetic.h>
#include <__utility/move.h> #include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -31,13 +33,23 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
__comp_ref_type<_Compare> __comp_ref = __comp; __comp_ref_type<_Compare> __comp_ref = __comp;
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; using __diff_t = __iterator_difference_type<_RandomAccessIterator>;
difference_type __n = __last - __first; const __diff_t __n = __last - __first;
const bool __assume_both_children = is_arithmetic<__iterator_value_type<_RandomAccessIterator> >::value;
// While it would be correct to always assume we have both children, in practice we observed this to be a performance
// improvement only for arithmetic types.
const __diff_t __sift_down_n = __assume_both_children ? ((__n & 1) ? __n : __n - 1) : __n;
if (__n > 1) { if (__n > 1) {
// start from the first parent, there is no need to consider children // start from the first parent, there is no need to consider children
for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) {
std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start); for (__diff_t __start = (__sift_down_n - 2) / 2; __start >= 0; --__start) {
std::__sift_down<_AlgPolicy, __assume_both_children>(__first, __comp_ref, __sift_down_n, __start);
} }
if _LIBCPP_CONSTEXPR (__assume_both_children)
std::__sift_up<_AlgPolicy>(__first, __last, __comp, __n);
} }
} }
+2 -2
View File
@@ -60,7 +60,7 @@ __mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Pro
template <class _Iter> template <class _Iter>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter> [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter>
__mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) {
using __value_type = __iter_value_type<_Iter>; using __value_type = __iterator_value_type<_Iter>;
constexpr size_t __unroll_count = 4; constexpr size_t __unroll_count = 4;
constexpr size_t __vec_size = __native_vector_size<__value_type>; constexpr size_t __vec_size = __native_vector_size<__value_type>;
using __vec = __simd_vector<__value_type, __vec_size>; using __vec = __simd_vector<__value_type, __vec_size>;
@@ -136,7 +136,7 @@ template <class _Tp,
class _Proj2, class _Proj2,
__enable_if_t<!is_integral<_Tp>::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && __enable_if_t<!is_integral<_Tp>::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> &&
__is_identity<_Proj1>::value && __is_identity<_Proj2>::value && __is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
__can_map_to_integer_v<_Tp> && __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value, __can_map_to_integer_v<_Tp> && __is_trivially_equality_comparable_v<_Tp, _Tp>,
int> = 0> int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*>
__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+8 -19
View File
@@ -50,37 +50,26 @@ struct __move_impl {
return std::make_pair(std::move(__first), std::move(__result)); return std::make_pair(std::move(__first), std::move(__result));
} }
template <class _InIter, class _OutIter> template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
struct _MoveSegment {
using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>;
_OutIter& __result_;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _MoveSegment(_OutIter& __result)
: __result_(__result) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
__result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second;
}
};
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result)); using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
std::__for_each_segment(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
__result = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result)).second;
});
return std::make_pair(__last, std::move(__result)); return std::make_pair(__last, std::move(__result));
} }
template <class _InIter, template <class _InIter,
class _OutIter, class _OutIter,
__enable_if_t<__has_random_access_iterator_category<_InIter>::value && __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
!__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>,
int> = 0> int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_OutIter>; using _Traits = __segmented_iterator_traits<_OutIter>;
using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; using _DiffT =
typename common_type<__iterator_difference_type<_InIter>, __iterator_difference_type<_OutIter> >::type;
if (__first == __last) if (__first == __last)
return std::make_pair(std::move(__first), std::move(__result)); return std::make_pair(std::move(__first), std::move(__result));
+9 -24
View File
@@ -11,6 +11,7 @@
#include <__algorithm/copy_backward.h> #include <__algorithm/copy_backward.h>
#include <__algorithm/copy_move_common.h> #include <__algorithm/copy_move_common.h>
#include <__algorithm/for_each_segment.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h> #include <__algorithm/min.h>
#include <__config> #include <__config>
@@ -51,42 +52,26 @@ struct __move_backward_impl {
return std::make_pair(std::move(__original_last_iter), std::move(__result)); return std::make_pair(std::move(__original_last_iter), std::move(__result));
} }
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_InIter>; using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
auto __sfirst = _Traits::__segment(__first); std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
auto __slast = _Traits::__segment(__last); __result = std::__move_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result)).second;
if (__sfirst == __slast) { });
auto __iters =
std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
return std::make_pair(__last, __iters.second);
}
__result =
std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
.second;
--__slast;
while (__sfirst != __slast) {
__result =
std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
.second;
--__slast;
}
__result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
.second;
return std::make_pair(__last, std::move(__result)); return std::make_pair(__last, std::move(__result));
} }
template <class _InIter, template <class _InIter,
class _OutIter, class _OutIter,
__enable_if_t<__has_random_access_iterator_category<_InIter>::value && __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
!__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, !__is_segmented_iterator_v<_InIter> && __is_segmented_iterator_v<_OutIter>,
int> = 0> int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const { operator()(_InIter __first, _InIter __last, _OutIter __result) const {
using _Traits = __segmented_iterator_traits<_OutIter>; using _Traits = __segmented_iterator_traits<_OutIter>;
using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; using _DiffT =
typename common_type<__iterator_difference_type<_InIter>, __iterator_difference_type<_OutIter> >::type;
// When the range contains no elements, __result might not be a valid iterator // When the range contains no elements, __result might not be a valid iterator
if (__first == __last) if (__first == __last)
+4 -4
View File
@@ -10,7 +10,9 @@
#ifndef _LIBCPP___ALGORITHM_NONE_OF_H #ifndef _LIBCPP___ALGORITHM_NONE_OF_H
#define _LIBCPP___ALGORITHM_NONE_OF_H #define _LIBCPP___ALGORITHM_NONE_OF_H
#include <__algorithm/any_of.h>
#include <__config> #include <__config>
#include <__functional/identity.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -21,10 +23,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first) __identity __proj;
if (__pred(*__first)) return !std::__any_of(__first, __last, __pred, __proj);
return false;
return true;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+1 -1
View File
@@ -45,7 +45,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator __part
for (; __i != __last; ++__i) { for (; __i != __last; ++__i) {
if (__comp(*__i, *__first)) { if (__comp(*__i, *__first)) {
_IterOps<_AlgPolicy>::iter_swap(__i, __first); _IterOps<_AlgPolicy>::iter_swap(__i, __first);
std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first); std::__sift_down<_AlgPolicy, false>(__first, __comp, __len, 0);
} }
} }
std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp);
+1 -1
View File
@@ -60,7 +60,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator, _Random
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) { if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) {
*__result_first = *__first; *__result_first = *__first;
std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first); std::__sift_down<_AlgPolicy, false>(__result_first, __projected_comp, __len, 0);
} }
std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp); std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
} }
+9 -9
View File
@@ -115,7 +115,7 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __iterator_difference_type<_ForwardIterator>
count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(
_ForwardIterator, "count_if(first, last, pred) requires [first, last) to be ForwardIterators"); _ForwardIterator, "count_if(first, last, pred) requires [first, last) to be ForwardIterators");
@@ -129,7 +129,7 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __iterator_difference_type<_ForwardIterator>
count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(
_ForwardIterator, "count(first, last, val) requires [first, last) to be ForwardIterators"); _ForwardIterator, "count(first, last, val) requires [first, last) to be ForwardIterators");
@@ -144,7 +144,7 @@ template <class _ExecutionPolicy,
class _Pred, class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy, equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@@ -166,7 +166,7 @@ template <class _ExecutionPolicy,
class _ForwardIterator2, class _ForwardIterator2,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators"); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators");
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators"); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators");
@@ -185,7 +185,7 @@ template <class _ExecutionPolicy,
class _Pred, class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy, equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@@ -209,7 +209,7 @@ template <class _ExecutionPolicy,
class _ForwardIterator2, class _ForwardIterator2,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy, equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@@ -259,7 +259,7 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator
find_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { find_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if requires ForwardIterators"); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__find_if, __pstl::__current_configuration, _RawPolicy>; using _Implementation = __pstl::__dispatch<__pstl::__find_if, __pstl::__current_configuration, _RawPolicy>;
@@ -272,7 +272,7 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator
find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if_not requires ForwardIterators"); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if_not requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__find_if_not, __pstl::__current_configuration, _RawPolicy>; using _Implementation = __pstl::__dispatch<__pstl::__find_if_not, __pstl::__current_configuration, _RawPolicy>;
@@ -285,7 +285,7 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator
find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find requires ForwardIterators"); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__find, __pstl::__current_configuration, _RawPolicy>; using _Implementation = __pstl::__dispatch<__pstl::__find, __pstl::__current_configuration, _RawPolicy>;
+27 -25
View File
@@ -72,14 +72,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
template <class _InputIterator, class _OutputIterator> template <class _InputIterator, class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI constexpr pair<_OutputIterator, __iter_value_type<_InputIterator>> _LIBCPP_HIDE_FROM_ABI constexpr pair<_OutputIterator, __iterator_value_type<_InputIterator>>
__partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
if (__first == __last) if (__first == __last)
return {__result, 0}; return {__result, 0};
auto __max = *__first; auto __max = *__first;
__iter_value_type<_InputIterator> __sum = *__first; __iterator_value_type<_InputIterator> __sum = *__first;
*__result = __sum; *__result = __sum;
while (++__first != __last) { while (++__first != __last) {
if (__max < *__first) { if (__max < *__first) {
@@ -124,7 +124,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __nth_radix(size_t __radix_number, _Radix _
template <class _ForwardIterator, class _Map, class _RandomAccessIterator> template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI constexpr void _LIBCPP_HIDE_FROM_ABI constexpr void
__collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) { __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
using __value_type = __iter_value_type<_ForwardIterator>; using __value_type = __iterator_value_type<_ForwardIterator>;
using __traits = __counting_sort_traits<__value_type, _Map>; using __traits = __counting_sort_traits<__value_type, _Map>;
std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; }); std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
@@ -160,7 +160,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __collect_impl(
_RandomAccessIterator1 __counters, _RandomAccessIterator1 __counters,
_RandomAccessIterator2 __maximums, _RandomAccessIterator2 __maximums,
index_sequence<_Radices...>) { index_sequence<_Radices...>) {
using __value_type = __iter_value_type<_ForwardIterator>; using __value_type = __iterator_value_type<_ForwardIterator>;
constexpr auto __radix_value_range = __radix_sort_traits<__value_type, _Map, _Radix>::__radix_value_range; constexpr auto __radix_value_range = __radix_sort_traits<__value_type, _Map, _Radix>::__radix_value_range;
auto __previous = numeric_limits<__invoke_result_t<_Map, __value_type>>::min(); auto __previous = numeric_limits<__invoke_result_t<_Map, __value_type>>::min();
@@ -189,7 +189,7 @@ __collect(_ForwardIterator __first,
_Radix __radix, _Radix __radix,
_RandomAccessIterator1 __counters, _RandomAccessIterator1 __counters,
_RandomAccessIterator2 __maximums) { _RandomAccessIterator2 __maximums) {
using __value_type = __iter_value_type<_ForwardIterator>; using __value_type = __iterator_value_type<_ForwardIterator>;
constexpr auto __radix_count = __radix_sort_traits<__value_type, _Map, _Radix>::__radix_count; constexpr auto __radix_count = __radix_sort_traits<__value_type, _Map, _Radix>::__radix_count;
return std::__collect_impl( return std::__collect_impl(
__first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>()); __first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
@@ -213,10 +213,10 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __dispose_backward(
template <class _ForwardIterator, class _RandomAccessIterator, class _Map> template <class _ForwardIterator, class _RandomAccessIterator, class _Map>
_LIBCPP_HIDE_FROM_ABI constexpr _RandomAccessIterator _LIBCPP_HIDE_FROM_ABI constexpr _RandomAccessIterator
__counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) { __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
using __value_type = __iter_value_type<_ForwardIterator>; using __value_type = __iterator_value_type<_ForwardIterator>;
using __traits = __counting_sort_traits<__value_type, _Map>; using __traits = __counting_sort_traits<__value_type, _Map>;
__iter_diff_t<_RandomAccessIterator> __counters[__traits::__value_range + 1] = {0}; __iterator_difference_type<_RandomAccessIterator> __counters[__traits::__value_range + 1] = {0};
std::__collect(__first, __last, __map, std::next(std::begin(__counters))); std::__collect(__first, __last, __map, std::next(std::begin(__counters)));
std::__dispose(__first, __last, __result, __map, std::begin(__counters)); std::__dispose(__first, __last, __result, __map, std::begin(__counters));
@@ -224,12 +224,13 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
return __result + __counters[__traits::__value_range]; return __result + __counters[__traits::__value_range];
} }
template <class _RandomAccessIterator1, template <
class _RandomAccessIterator2, class _RandomAccessIterator1,
class _Map, class _RandomAccessIterator2,
class _Radix, class _Map,
enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1, class _Radix,
int> = 0> enable_if_t<__radix_sort_traits<__iterator_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1,
int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl( _LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl(
_RandomAccessIterator1 __first, _RandomAccessIterator1 __first,
_RandomAccessIterator1 __last, _RandomAccessIterator1 __last,
@@ -243,24 +244,25 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl(
std::move(__buffer, __buffer_end, __first); std::move(__buffer, __buffer_end, __first);
} }
template < template <class _RandomAccessIterator1,
class _RandomAccessIterator1, class _RandomAccessIterator2,
class _RandomAccessIterator2, class _Map,
class _Map, class _Radix,
class _Radix, enable_if_t<
enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0, __radix_sort_traits<__iterator_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0,
int> = 0 > int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl( _LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl(
_RandomAccessIterator1 __first, _RandomAccessIterator1 __first,
_RandomAccessIterator1 __last, _RandomAccessIterator1 __last,
_RandomAccessIterator2 __buffer_begin, _RandomAccessIterator2 __buffer_begin,
_Map __map, _Map __map,
_Radix __radix) { _Radix __radix) {
using __value_type = __iter_value_type<_RandomAccessIterator1>; using __value_type = __iterator_value_type<_RandomAccessIterator1>;
using __traits = __radix_sort_traits<__value_type, _Map, _Radix>; using __traits = __radix_sort_traits<__value_type, _Map, _Radix>;
__iter_diff_t<_RandomAccessIterator1> __counters[__traits::__radix_count][__traits::__radix_value_range] = {{0}}; __iterator_difference_type<_RandomAccessIterator1>
__iter_diff_t<_RandomAccessIterator1> __maximums[__traits::__radix_count] = {0}; __counters[__traits::__radix_count][__traits::__radix_value_range] = {{0}};
__iterator_difference_type<_RandomAccessIterator1> __maximums[__traits::__radix_count] = {0};
const auto __is_sorted = std::__collect(__first, __last, __map, __radix, __counters, __maximums); const auto __is_sorted = std::__collect(__first, __last, __map, __radix, __counters, __maximums);
if (!__is_sorted) { if (!__is_sorted) {
const auto __range_size = std::distance(__first, __last); const auto __range_size = std::distance(__first, __last);
+3 -26
View File
@@ -9,16 +9,12 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_COPY_N_H #ifndef _LIBCPP___ALGORITHM_RANGES_COPY_N_H
#define _LIBCPP___ALGORITHM_RANGES_COPY_N_H #define _LIBCPP___ALGORITHM_RANGES_COPY_N_H
#include <__algorithm/copy.h> #include <__algorithm/copy_n.h>
#include <__algorithm/in_out_result.h> #include <__algorithm/in_out_result.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/ranges_copy.h>
#include <__config> #include <__config>
#include <__functional/identity.h>
#include <__iterator/concepts.h> #include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h> #include <__iterator/incrementable_traits.h>
#include <__iterator/unreachable_sentinel.h>
#include <__iterator/wrap_iter.h>
#include <__utility/move.h> #include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -37,32 +33,13 @@ namespace ranges {
template <class _Ip, class _Op> template <class _Ip, class _Op>
using copy_n_result = in_out_result<_Ip, _Op>; using copy_n_result = in_out_result<_Ip, _Op>;
// TODO: Merge this with copy_n
struct __copy_n { struct __copy_n {
template <class _InIter, class _DiffType, class _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
__go(_InIter __first, _DiffType __n, _OutIter __result) {
while (__n != 0) {
*__result = *__first;
++__first;
++__result;
--__n;
}
return {std::move(__first), std::move(__result)};
}
template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter>
__go(_InIter __first, _DiffType __n, _OutIter __result) {
auto __ret = std::__copy(__first, __first + __n, __result);
return {__ret.first, __ret.second};
}
template <input_iterator _Ip, weakly_incrementable _Op> template <input_iterator _Ip, weakly_incrementable _Op>
requires indirectly_copyable<_Ip, _Op> requires indirectly_copyable<_Ip, _Op>
_LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op> _LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op>
operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const {
return __go(std::move(__first), __n, std::move(__result)); auto __res = std::__copy_n<_RangeAlgPolicy>(std::move(__first), __n, std::move(__result));
return {std::move(__res.first), std::move(__res.second)};
} }
}; };
+17 -26
View File
@@ -13,13 +13,12 @@
#include <__algorithm/unwrap_range.h> #include <__algorithm/unwrap_range.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h> #include <__functional/ranges_operations.h>
#include <__iterator/concepts.h> #include <__iterator/concepts.h>
#include <__iterator/distance.h>
#include <__iterator/indirectly_comparable.h> #include <__iterator/indirectly_comparable.h>
#include <__ranges/access.h> #include <__ranges/access.h>
#include <__ranges/concepts.h> #include <__ranges/concepts.h>
#include <__ranges/size.h>
#include <__utility/move.h> #include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -51,20 +50,17 @@ struct __equal {
_Pred __pred = {}, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const { _Proj2 __proj2 = {}) const {
if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) { static constexpr bool __both_sized = sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>;
if constexpr (__both_sized) {
if (__last1 - __first1 != __last2 - __first2) if (__last1 - __first1 != __last2 - __first2)
return false; return false;
} }
auto __unwrapped1 = std::__unwrap_range(std::move(__first1), std::move(__last1));
auto __unwrapped2 = std::__unwrap_range(std::move(__first2), std::move(__last2)); auto [__ufirst1, __ulast1] = std::__unwrap_range(std::move(__first1), std::move(__last1));
return std::__equal_impl( auto [__ufirst2, __ulast2] = std::__unwrap_range(std::move(__first2), std::move(__last2));
std::move(__unwrapped1.first),
std::move(__unwrapped1.second), return std::__equal_impl<__both_sized>(
std::move(__unwrapped2.first), std::move(__ufirst1), std::move(__ulast1), std::move(__ufirst2), std::move(__ulast2), __pred, __proj1, __proj2);
std::move(__unwrapped2.second),
__pred,
__proj1,
__proj2);
} }
template <input_range _Range1, template <input_range _Range1,
@@ -75,21 +71,16 @@ struct __equal {
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
if constexpr (sized_range<_Range1> && sized_range<_Range2>) { static constexpr bool __both_sized = sized_range<_Range1> && sized_range<_Range2>;
if (ranges::distance(__range1) != ranges::distance(__range2)) if constexpr (__both_sized) {
if (ranges::size(__range1) != ranges::size(__range2))
return false; return false;
} }
auto __unwrapped1 = std::__unwrap_range(ranges::begin(__range1), ranges::end(__range1));
auto __unwrapped2 = std::__unwrap_range(ranges::begin(__range2), ranges::end(__range2)); auto [__ufirst1, __ulast1] = std::__unwrap_range(ranges::begin(__range1), ranges::end(__range1));
return std::__equal_impl( auto [__ufirst2, __ulast2] = std::__unwrap_range(ranges::begin(__range2), ranges::end(__range2));
std::move(__unwrapped1.first), return std::__equal_impl<__both_sized>(
std::move(__unwrapped1.second), std::move(__ufirst1), std::move(__ulast1), std::move(__ufirst2), std::move(__ulast2), __pred, __proj1, __proj2);
std::move(__unwrapped2.first),
std::move(__unwrapped2.second),
__pred,
__proj1,
__proj2);
return false;
} }
}; };
+7 -6
View File
@@ -9,12 +9,14 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_FILL_H #ifndef _LIBCPP___ALGORITHM_RANGES_FILL_H
#define _LIBCPP___ALGORITHM_RANGES_FILL_H #define _LIBCPP___ALGORITHM_RANGES_FILL_H
#include <__algorithm/ranges_fill_n.h> #include <__algorithm/fill.h>
#include <__algorithm/fill_n.h>
#include <__config> #include <__config>
#include <__iterator/concepts.h> #include <__iterator/concepts.h>
#include <__ranges/access.h> #include <__ranges/access.h>
#include <__ranges/concepts.h> #include <__ranges/concepts.h>
#include <__ranges/dangling.h> #include <__ranges/dangling.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -31,12 +33,11 @@ namespace ranges {
struct __fill { struct __fill {
template <class _Type, output_iterator<const _Type&> _Iter, sentinel_for<_Iter> _Sent> template <class _Type, output_iterator<const _Type&> _Iter, sentinel_for<_Iter> _Sent>
_LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const {
if constexpr (random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { if constexpr (sized_sentinel_for<_Sent, _Iter>) {
return ranges::fill_n(__first, __last - __first, __value); auto __n = __last - __first;
return std::__fill_n(std::move(__first), __n, __value);
} else { } else {
for (; __first != __last; ++__first) return std::__fill(std::move(__first), std::move(__last), __value);
*__first = __value;
return __first;
} }
} }
+9 -1
View File
@@ -12,6 +12,7 @@
#include <__algorithm/for_each.h> #include <__algorithm/for_each.h>
#include <__algorithm/for_each_n.h> #include <__algorithm/for_each_n.h>
#include <__algorithm/in_fun_result.h> #include <__algorithm/in_fun_result.h>
#include <__algorithm/specialized_algorithms.h>
#include <__concepts/assignable.h> #include <__concepts/assignable.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
@@ -20,6 +21,7 @@
#include <__ranges/access.h> #include <__ranges/access.h>
#include <__ranges/concepts.h> #include <__ranges/concepts.h>
#include <__ranges/dangling.h> #include <__ranges/dangling.h>
#include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -71,7 +73,13 @@ public:
indirectly_unary_invocable<projected<iterator_t<_Range>, _Proj>> _Func> indirectly_unary_invocable<projected<iterator_t<_Range>, _Proj>> _Func>
_LIBCPP_HIDE_FROM_ABI constexpr for_each_result<borrowed_iterator_t<_Range>, _Func> _LIBCPP_HIDE_FROM_ABI constexpr for_each_result<borrowed_iterator_t<_Range>, _Func>
operator()(_Range&& __range, _Func __func, _Proj __proj = {}) const { operator()(_Range&& __range, _Func __func, _Proj __proj = {}) const {
return __for_each_impl(ranges::begin(__range), ranges::end(__range), __func, __proj); using _SpecialAlg = __specialized_algorithm<_Algorithm::__for_each, __single_range<remove_cvref_t<_Range>>>;
if constexpr (_SpecialAlg::__has_algorithm) {
auto [__iter, __func2] = _SpecialAlg()(__range, std::move(__func), std::move(__proj));
return {std::move(__iter), std::move(__func)};
} else {
return __for_each_impl(ranges::begin(__range), ranges::end(__range), __func, __proj);
}
} }
}; };
+2 -6
View File
@@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H #ifndef _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H
#define _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H #define _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H
#include <__algorithm/generate_n.h>
#include <__concepts/constructible.h> #include <__concepts/constructible.h>
#include <__concepts/invocable.h> #include <__concepts/invocable.h>
#include <__config> #include <__config>
@@ -38,12 +39,7 @@ struct __generate_n {
requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>>
_LIBCPP_HIDE_FROM_ABI constexpr _OutIter _LIBCPP_HIDE_FROM_ABI constexpr _OutIter
operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const {
for (; __n > 0; --__n) { return std::__generate_n(std::move(__first), __n, __gen);
*__first = __gen();
++__first;
}
return __first;
} }
}; };
+2 -2
View File
@@ -54,8 +54,8 @@ struct __search_n {
} }
if constexpr (random_access_iterator<_Iter1>) { if constexpr (random_access_iterator<_Iter1>) {
auto __ret = std::__search_n_random_access_impl<_RangeAlgPolicy>( auto __ret =
__first, __last, __count, __value, __pred, __proj, __size); std::__search_n_random_access_impl<_RangeAlgPolicy>(__first, __count, __value, __pred, __proj, __size);
return {std::move(__ret.first), std::move(__ret.second)}; return {std::move(__ret.first), std::move(__ret.second)};
} }
} }
+25 -42
View File
@@ -12,16 +12,13 @@
#include <__algorithm/copy.h> #include <__algorithm/copy.h>
#include <__algorithm/copy_backward.h> #include <__algorithm/copy_backward.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__algorithm/move.h> #include <__algorithm/move.h>
#include <__algorithm/move_backward.h> #include <__algorithm/move_backward.h>
#include <__algorithm/swap_ranges.h> #include <__algorithm/swap_ranges.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__fwd/bit_reference.h> #include <__fwd/bit_reference.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__memory/construct_at.h>
#include <__memory/pointer_traits.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_trivially_assignable.h> #include <__type_traits/is_trivially_assignable.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/pair.h> #include <__utility/pair.h>
@@ -89,46 +86,32 @@ __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIt
return __r; return __r;
} }
template <typename _Integral> template <class _AlgPolicy, class _Iter, class _Sent>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Integral __algo_gcd(_Integral __x, _Integral __y) { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter
do { __rotate_random_access(_Iter __first, _Iter __middle, _Sent __sent) {
_Integral __t = __x % __y; auto __left = _IterOps<_AlgPolicy>::distance(__first, __middle);
__x = __y; auto __right = _IterOps<_AlgPolicy>::distance(__middle, __sent);
__y = __t; auto __last = __first + __right;
} while (__y);
return __x;
}
template <class _AlgPolicy, typename _RandomAccessIterator> auto __min_len = std::min(__left, __right);
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _RandomAccessIterator
__rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) {
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
using _Ops = _IterOps<_AlgPolicy>;
const difference_type __m1 = __middle - __first; while (__min_len > 0) {
const difference_type __m2 = _Ops::distance(__middle, __last); if (__left <= __right) {
if (__m1 == __m2) { do {
std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last); std::__swap_ranges<_AlgPolicy>(__first, __first + __left, __first + __left);
return __middle; __first += __left;
__right -= __left;
} while (__left <= __right);
__min_len = __right;
} else {
do {
std::__swap_ranges<_AlgPolicy>(__first + (__left - __right), __first + __left, __first + __left);
__left -= __right;
} while (__left > __right);
__min_len = __left;
}
} }
const difference_type __g = std::__algo_gcd(__m1, __m2); return __last;
for (_RandomAccessIterator __p = __first + __g; __p != __first;) {
value_type __t(_Ops::__iter_move(--__p));
_RandomAccessIterator __p1 = __p;
_RandomAccessIterator __p2 = __p1 + __m1;
do {
*__p1 = _Ops::__iter_move(__p2);
__p1 = __p2;
const difference_type __d = _Ops::distance(__p2, __last);
if (__m1 < __d)
__p2 += __m1;
else
__p2 = __first + (__m1 - __d);
} while (__p2 != __p);
*__p1 = std::move(__t);
}
return __first + __m2;
} }
template <class _AlgPolicy, class _ForwardIterator> template <class _AlgPolicy, class _ForwardIterator>
@@ -170,7 +153,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator
return std::__rotate_left<_AlgPolicy>(__first, __last); return std::__rotate_left<_AlgPolicy>(__first, __last);
if (_IterOps<_AlgPolicy>::next(__middle) == __last) if (_IterOps<_AlgPolicy>::next(__middle) == __last)
return std::__rotate_right<_AlgPolicy>(__first, __last); return std::__rotate_right<_AlgPolicy>(__first, __last);
return std::__rotate_gcd<_AlgPolicy>(__first, __middle, __last); return std::__rotate_random_access<_AlgPolicy>(__first, __middle, __last);
} }
return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last);
} }
+49 -37
View File
@@ -14,11 +14,7 @@
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__iterator/advance.h>
#include <__iterator/concepts.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__ranges/concepts.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__type_traits/is_callable.h> #include <__type_traits/is_callable.h>
@@ -68,44 +64,60 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> __search_
} }
} }
template <class _AlgPolicy, class _Pred, class _Iter, class _Sent, class _SizeT, class _Type, class _Proj, class _DiffT> // Finds the longest suffix in [__first, __last) where each element satisfies __pred.
template <class _RAIter, class _Pred, class _Proj, class _ValueT>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RAIter
__find_longest_suffix(_RAIter __first, _RAIter __last, const _ValueT& __value, _Pred& __pred, _Proj& __proj) {
while (__first != __last) {
if (!std::__invoke(__pred, std::__invoke(__proj, *--__last), __value)) {
return ++__last;
}
}
return __first;
}
template <class _AlgPolicy, class _Pred, class _Iter, class _SizeT, class _Type, class _Proj, class _DiffT>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 std::pair<_Iter, _Iter> __search_n_random_access_impl( _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 std::pair<_Iter, _Iter> __search_n_random_access_impl(
_Iter __first, _Sent __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size1) { _Iter __first, _SizeT __count_in, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size) {
using difference_type = typename iterator_traits<_Iter>::difference_type; auto __last = __first + __size;
auto __count = static_cast<_DiffT>(__count_in);
if (__count == 0) if (__count == 0)
return std::make_pair(__first, __first); return std::make_pair(__first, __first);
if (__size1 < static_cast<_DiffT>(__count)) { if (__size < __count)
_IterOps<_AlgPolicy>::__advance_to(__first, __last); return std::make_pair(__last, __last);
return std::make_pair(__first, __first);
} // [__match_start, __match_start + __count) is the subrange which we currently check whether it only contains matching
// elements. This subrange is returned in case all the elements match.
// [__match_start, __matched_until) is the longest subrange where all elements are known to match at any given point
// in time.
// [__matched_until, __match_start + __count) is the subrange where we don't know whether the elements match.
// This algorithm tries to expand the subrange [__match_start, __matched_until) into a range of sufficient length.
// When we fail to do that because we find a mismatching element, we move it forward to the beginning of the next
// consecutive sequence that is not known not to match.
const _Iter __try_match_until = __last - __count;
_Iter __match_start = __first;
_Iter __matched_until = __first;
const auto __s = __first + __size1 - difference_type(__count - 1); // Start of pattern match can't go beyond here
while (true) { while (true) {
// Find first element in sequence that matchs __value, with a mininum of loop checks // There's no chance of expanding the subrange into a sequence of sufficient length, since we don't have enough
while (true) { // elements in the haystack anymore.
if (__first >= __s) { // return __last if no element matches __value if (__match_start > __try_match_until)
_IterOps<_AlgPolicy>::__advance_to(__first, __last); return std::make_pair(__last, __last);
return std::make_pair(__first, __first);
}
if (std::__invoke(__pred, std::__invoke(__proj, *__first), __value))
break;
++__first;
}
// *__first matches __value_, now match elements after here
auto __m = __first;
_SizeT __c(0);
while (true) {
if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern)
return std::make_pair(__first, __first + _DiffT(__count));
++__m; // no need to check range on __m because __s guarantees we have enough source
// if there is a mismatch, restart with a new __first auto __mismatch = std::__find_longest_suffix(__matched_until, __match_start + __count, __value, __pred, __proj);
if (!std::__invoke(__pred, std::__invoke(__proj, *__m), __value)) {
__first = __m; // If all elements in [__matched_until, __match_start + __count) match, we know that
++__first; // [__match_start, __match_start + __count) is a full sequence of matching elements, so we're done.
break; if (__mismatch == __matched_until)
} // else there is a match, check next elements return std::make_pair(__match_start, __match_start + __count);
}
// Otherwise, we have to move the [__match_start, __matched_until) subrange forward past the point where we know for
// sure a match is impossible.
__matched_until = __match_start + __count;
__match_start = __mismatch;
} }
} }
@@ -119,7 +131,7 @@ template <class _Iter,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
__search_n_impl(_Iter __first, _Sent __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) { __search_n_impl(_Iter __first, _Sent __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
return std::__search_n_random_access_impl<_ClassicAlgPolicy>( return std::__search_n_random_access_impl<_ClassicAlgPolicy>(
__first, __last, __count, __value, __pred, __proj, __last - __first); __first, __count, __value, __pred, __proj, __last - __first);
} }
template <class _Iter1, template <class _Iter1,
+19 -18
View File
@@ -24,59 +24,60 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, bool __assume_both_children, class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__sift_down(_RandomAccessIterator __first, __sift_down(_RandomAccessIterator __first,
_Compare&& __comp, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len, __iterator_difference_type<_RandomAccessIterator> __len,
_RandomAccessIterator __start) { __iterator_difference_type<_RandomAccessIterator> __start) {
using _Ops = _IterOps<_AlgPolicy>; using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
// left-child of __start is at 2 * __start + 1 // left-child of __start is at 2 * __start + 1
// right-child of __start is at 2 * __start + 2 // right-child of __start is at 2 * __start + 2
difference_type __child = __start - __first; difference_type __child = __start;
if (__len < 2 || (__len - 2) / 2 < __child) if (__len < 2 || (__len - 2) / 2 < __child)
return; return;
__child = 2 * __child + 1; __child = 2 * __child + 1;
_RandomAccessIterator __child_i = __first + __child;
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { if _LIBCPP_CONSTEXPR (__assume_both_children) {
// right-child exists and is greater than left-child
__child += __comp(__first[__child], __first[__child + 1]);
} else if ((__child + 1) < __len && __comp(__first[__child], __first[__child + 1])) {
// right-child exists and is greater than left-child // right-child exists and is greater than left-child
++__child_i;
++__child; ++__child;
} }
// check if we are in heap-order // check if we are in heap-order
if (__comp(*__child_i, *__start)) if (__comp(__first[__child], __first[__start]))
// we are, __start is larger than its largest child // we are, __start is larger than its largest child
return; return;
value_type __top(_Ops::__iter_move(__start)); value_type __top(_Ops::__iter_move(__first + __start));
do { do {
// we are not in heap-order, swap the parent with its largest child // we are not in heap-order, swap the parent with its largest child
*__start = _Ops::__iter_move(__child_i); __first[__start] = _Ops::__iter_move(__first + __child);
__start = __child_i; __start = __child;
if ((__len - 2) / 2 < __child) if ((__len - 2) / 2 < __child)
break; break;
// recompute the child based off of the updated parent // recompute the child based off of the updated parent
__child = 2 * __child + 1; __child = 2 * __child + 1;
__child_i = __first + __child;
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { if _LIBCPP_CONSTEXPR (__assume_both_children) {
__child += __comp(__first[__child], __first[__child + 1]);
} else if ((__child + 1) < __len && __comp(__first[__child], __first[__child + 1])) {
// right-child exists and is greater than left-child // right-child exists and is greater than left-child
++__child_i;
++__child; ++__child;
} }
// check if we are in heap-order // check if we are in heap-order
} while (!__comp(*__child_i, __top)); } while (!__comp(__first[__child], __top));
*__start = std::move(__top); __first[__start] = std::move(__top);
} }
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
+33 -4
View File
@@ -26,9 +26,7 @@ _LIBCPP_PUSH_MACROS
#include <__undef_macros> #include <__undef_macros>
// TODO: Find out how altivec changes things and allow vectorizations there too. // TODO: Find out how altivec changes things and allow vectorizations there too.
// TODO: Simplify this condition once we stop building with AppleClang 15 in the CI. #if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__)
#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__) && \
!(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600)
# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1 # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1
#else #else
# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0 # define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0
@@ -116,16 +114,47 @@ template <class _VecT, class _Iter>
}(make_index_sequence<__simd_vector_size_v<_VecT>>{}); }(make_index_sequence<__simd_vector_size_v<_VecT>>{});
} }
// Load the first _Np elements, zero the rest
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wpsabi")
template <class _VecT, size_t _Np, class _Iter>
[[__nodiscard__]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __partial_load(_Iter __iter) noexcept {
return [=]<size_t... _LoadIndices, size_t... _ZeroIndices>(
index_sequence<_LoadIndices...>, index_sequence<_ZeroIndices...>) _LIBCPP_ALWAYS_INLINE noexcept {
return _VecT{__iter[_LoadIndices]..., ((void)_ZeroIndices, 0)...};
}(make_index_sequence<_Np>{}, make_index_sequence<__simd_vector_size_v<_VecT> - _Np>{});
}
// Create a vector where every elements is __val
template <class _VecT>
[[__nodiscard__]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT
__broadcast(__simd_vector_underlying_type_t<_VecT> __val) {
return [&]<std::size_t... _Indices>(index_sequence<_Indices...>) {
return _VecT{((void)_Indices, __val)...};
}(make_index_sequence<__simd_vector_size_v<_VecT>>());
}
_LIBCPP_DIAGNOSTIC_POP
template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __any_of(__simd_vector<_Tp, _Np> __vec) noexcept {
return __builtin_reduce_or(__builtin_convertvector(__vec, __simd_vector<bool, _Np>));
}
template <class _Tp, size_t _Np> template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept {
return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>));
} }
template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __none_of(__simd_vector<_Tp, _Np> __vec) noexcept {
return !__builtin_reduce_or(__builtin_convertvector(__vec, __simd_vector<bool, _Np>));
}
template <class _Tp, size_t _Np> template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
using __mask_vec = __simd_vector<bool, _Np>; using __mask_vec = __simd_vector<bool, _Np>;
// This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876 // This has MSan disabled du to https://llvm.org/PR85876
auto __impl = [&]<class _MaskT>(_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept { auto __impl = [&]<class _MaskT>(_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept {
# if defined(_LIBCPP_BIG_ENDIAN) # if defined(_LIBCPP_BIG_ENDIAN)
return std::min<size_t>( return std::min<size_t>(
+54
View File
@@ -0,0 +1,54 @@
//===----------------------------------------------------------------------===//
//
// 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_SPECIALIZED_ALGORITHMS_H
#define _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
#include <__config>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
namespace _Algorithm {
struct __copy {};
struct __fill_n {};
struct __for_each {};
} // namespace _Algorithm
template <class>
struct __single_iterator;
template <class, class>
struct __iterator_pair;
template <class>
struct __single_range;
// This struct allows specializing algorithms for specific arguments. This is useful when we know a more efficient
// algorithm implementation for e.g. library-defined iterators. _Alg is one of tags defined inside the _Algorithm
// namespace above. _Ranges is an essentially arbitrary subset of the arguments to the algorithm that are used for
// dispatching. This set is specific to the algorithm: look at each algorithm to see which arguments they use for
// dispatching to specialized algorithms.
//
// A specialization of `__specialized_algorithm` has to define `__has_algorithm` to true for the specialized algorithm
// to be used. This is intended for cases where iterators can do generic unwrapping and forward to a different
// specialization of `__specialized_algorithm`.
//
// If __has_algorithm is true, there has to be an operator() which will get called with the actual arguments to the
// algorithm.
template <class _Alg, class... _Ranges>
struct __specialized_algorithm {
static const bool __has_algorithm = false;
};
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
+1 -1
View File
@@ -247,7 +247,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >; constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >;
constexpr auto __radix_sortable = constexpr auto __radix_sortable =
__is_ordered_integer_representable_v<value_type> && __is_ordered_integer_representable_v<value_type> &&
is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>; is_same_v< value_type&, __iterator_reference<_RandomAccessIterator>>;
if constexpr (__default_comp && __radix_sortable) { if constexpr (__default_comp && __radix_sortable) {
if (__len <= __buff_size && __len >= static_cast<difference_type>(std::__radix_sort_min_bound<value_type>()) && if (__len <= __buff_size && __len >= static_cast<difference_type>(std::__radix_sort_min_bound<value_type>()) &&
__len <= static_cast<difference_type>(std::__radix_sort_max_bound<value_type>())) { __len <= static_cast<difference_type>(std::__radix_sort_max_bound<value_type>())) {
+31 -4
View File
@@ -16,6 +16,7 @@
# include <__cxx03/__verbose_trap> # include <__cxx03/__verbose_trap>
#else #else
# include <__config> # include <__config>
# include <__log_hardening_failure>
# include <__verbose_abort> # include <__verbose_abort>
# include <__verbose_trap> # include <__verbose_trap>
#endif #endif
@@ -24,14 +25,40 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message) // Keep the old implementation that doesn't support assertion semantics for backward compatibility with the frozen C++03
// mode.
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
# else
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
# endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
#else #else
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message) # if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG # elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_HARDENING_FAILURE(message)
# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
# else
# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \
_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \
_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \
_LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#endif // _LIBCPP___ASSERTION_HANDLER #endif // _LIBCPP___ASSERTION_HANDLER
+36 -60
View File
@@ -10,7 +10,9 @@
#define _LIBCPP___ATOMIC_ATOMIC_H #define _LIBCPP___ATOMIC_ATOMIC_H
#include <__atomic/atomic_sync.h> #include <__atomic/atomic_sync.h>
#include <__atomic/atomic_waitable_traits.h>
#include <__atomic/check_memory_order.h> #include <__atomic/check_memory_order.h>
#include <__atomic/floating_point_helper.h>
#include <__atomic/is_always_lock_free.h> #include <__atomic/is_always_lock_free.h>
#include <__atomic/memory_order.h> #include <__atomic/memory_order.h>
#include <__atomic/support.h> #include <__atomic/support.h>
@@ -47,10 +49,10 @@ struct __atomic_base // false
static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value;
#endif #endif
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT {
return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>)); return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>));
} }
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT {
return static_cast<__atomic_base const volatile*>(this)->is_lock_free(); return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
} }
_LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
@@ -61,11 +63,11 @@ struct __atomic_base // false
_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
std::__cxx_atomic_store(std::addressof(__a_), __d, __m); std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
} }
_LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return std::__cxx_atomic_load(std::addressof(__a_), __m); return std::__cxx_atomic_load(std::addressof(__a_), __m);
} }
_LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return std::__cxx_atomic_load(std::addressof(__a_), __m); return std::__cxx_atomic_load(std::addressof(__a_), __m);
} }
@@ -113,22 +115,16 @@ struct __atomic_base // false
} }
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
volatile _NOEXCEPT {
std::__atomic_wait(*this, __v, __m); std::__atomic_wait(*this, __v, __m);
} }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
std::__atomic_wait(*this, __v, __m); std::__atomic_wait(*this, __v, __m);
} }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { std::__atomic_notify_one(*this); }
std::__atomic_notify_one(*this); _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }
} _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(*this); }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
std::__atomic_notify_all(*this);
}
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@@ -205,12 +201,15 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
_LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; } _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
}; };
#if _LIBCPP_STD_VER >= 20
// Here we need _IsIntegral because the default template argument is not enough // Here we need _IsIntegral because the default template argument is not enough
// e.g __atomic_base<int> is __atomic_base<int, true>, which inherits from // e.g __atomic_base<int> is __atomic_base<int, true>, which inherits from
// __atomic_base<int, false> and the caller of the wait function is // __atomic_base<int, false> and the caller of the wait function is
// __atomic_base<int, false>. So specializing __atomic_base<_Tp> does not work // __atomic_base<int, false>. So specializing __atomic_base<_Tp> does not work
template <class _Tp, bool _IsIntegral> template <class _Tp, bool _IsIntegral>
struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
using __value_type _LIBCPP_NODEBUG = _Tp;
static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) { static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) {
return __a.load(__order); return __a.load(__order);
} }
@@ -231,6 +230,8 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
} }
}; };
#endif // _LIBCPP_STD_VER >= 20
template <typename _Tp> template <typename _Tp>
struct __check_atomic_mandates { struct __check_atomic_mandates {
using type _LIBCPP_NODEBUG = _Tp; using type _LIBCPP_NODEBUG = _Tp;
@@ -324,50 +325,26 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
atomic& operator=(const atomic&) volatile = delete; atomic& operator=(const atomic&) volatile = delete;
}; };
#if _LIBCPP_STD_VER >= 20
template <class _Tp> template <class _Tp>
struct __atomic_waitable_traits<atomic<_Tp> > : __atomic_waitable_traits<__atomic_base<_Tp> > {}; struct __atomic_waitable_traits<atomic<_Tp> > : __atomic_waitable_traits<__atomic_base<_Tp> > {};
#if _LIBCPP_STD_VER >= 20
template <class _Tp> template <class _Tp>
requires is_floating_point_v<_Tp> requires is_floating_point_v<_Tp>
struct atomic<_Tp> : __atomic_base<_Tp> { struct atomic<_Tp> : __atomic_base<_Tp> {
private: private:
_LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() {
// Only x87-fp80 long double has 64-bit mantissa
return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;
}
_LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() {
# ifndef _LIBCPP_COMPILER_CLANG_BASED
return false;
# else
// The builtin __cxx_atomic_fetch_add errors during compilation for
// long double on platforms with fp80 format.
// For more details, see
// lib/Sema/SemaChecking.cpp function IsAllowedValueType
// LLVM Parser does not allow atomicrmw with x86_fp80 type.
// if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
// &Context.getTargetInfo().getLongDoubleFormat() ==
// &llvm::APFloat::x87DoubleExtended())
// For more info
// https://github.com/llvm/llvm-project/issues/68602
// https://reviews.llvm.org/D53965
return !__is_fp80_long_double();
# endif
}
template <class _This, class _Operation, class _BuiltinOp> template <class _This, class _Operation, class _BuiltinOp>
_LIBCPP_HIDE_FROM_ABI static _Tp _LIBCPP_HIDE_FROM_ABI static _Tp
__rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) { __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {
if constexpr (__has_rmw_builtin()) { if constexpr (std::__has_rmw_builtin<_Tp>()) {
return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m); return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);
} else { } else {
_Tp __old = __self.load(memory_order_relaxed); _Tp __old = __self.load(memory_order_relaxed);
_Tp __new = __operation(__old, __operand); _Tp __new = __operation(__old, __operand);
while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) { while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) {
# ifdef _LIBCPP_COMPILER_CLANG_BASED # ifdef _LIBCPP_COMPILER_CLANG_BASED
if constexpr (__is_fp80_long_double()) { if constexpr (std::__is_fp80_long_double<_Tp>()) {
// https://github.com/llvm/llvm-project/issues/47978 // https://llvm.org/PR47978
// clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak // clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak
// Note __old = __self.load(memory_order_relaxed) will not work // Note __old = __self.load(memory_order_relaxed) will not work
std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed);
@@ -462,12 +439,12 @@ public:
// atomic_is_lock_free // atomic_is_lock_free
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {
return __o->is_lock_free(); return __o->is_lock_free();
} }
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {
return __o->is_lock_free(); return __o->is_lock_free();
} }
@@ -516,25 +493,25 @@ atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, me
// atomic_load // atomic_load
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {
return __o->load(); return __o->load();
} }
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {
return __o->load(); return __o->load();
} }
// atomic_load_explicit // atomic_load_explicit
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return __o->load(__m); return __o->load(__m);
} }
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return __o->load(__m); return __o->load(__m);
} }
@@ -642,28 +619,27 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
// atomic_wait // atomic_wait
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void
atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT { atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
return __o->wait(__v); return __o->wait(__v);
} }
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
return __o->wait(__v); return __o->wait(__v);
} }
// atomic_wait_explicit // atomic_wait_explicit
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void
atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return __o->wait(__v, __m); return __o->wait(__v, __m);
} }
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void
atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
return __o->wait(__v, __m); return __o->wait(__v, __m);
@@ -672,22 +648,22 @@ atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __
// atomic_notify_one // atomic_notify_one
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {
__o->notify_one(); __o->notify_one();
} }
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {
__o->notify_one(); __o->notify_one();
} }
// atomic_notify_all // atomic_notify_all
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {
__o->notify_all(); __o->notify_all();
} }
template <class _Tp> template <class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {
__o->notify_all(); __o->notify_all();
} }
+19 -37
View File
@@ -10,6 +10,7 @@
#define _LIBCPP___ATOMIC_ATOMIC_FLAG_H #define _LIBCPP___ATOMIC_ATOMIC_FLAG_H
#include <__atomic/atomic_sync.h> #include <__atomic/atomic_sync.h>
#include <__atomic/atomic_waitable_traits.h>
#include <__atomic/contention_t.h> #include <__atomic/contention_t.h>
#include <__atomic/memory_order.h> #include <__atomic/memory_order.h>
#include <__atomic/support.h> #include <__atomic/support.h>
@@ -49,22 +50,16 @@ struct atomic_flag {
} }
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
volatile _NOEXCEPT {
std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
} }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
} }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { std::__atomic_notify_one(*this); }
std::__atomic_notify_one(*this); _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }
} _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(*this); }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
std::__atomic_notify_all(*this);
}
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
#endif #endif
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@@ -80,8 +75,11 @@ struct atomic_flag {
atomic_flag& operator=(const atomic_flag&) volatile = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete;
}; };
#if _LIBCPP_STD_VER >= 20
template <> template <>
struct __atomic_waitable_traits<atomic_flag> { struct __atomic_waitable_traits<atomic_flag> {
using __value_type _LIBCPP_NODEBUG = _LIBCPP_ATOMIC_FLAG_TYPE;
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __atomic_load(const atomic_flag& __a, memory_order __order) { static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __atomic_load(const atomic_flag& __a, memory_order __order) {
return std::__cxx_atomic_load(&__a.__a_, __order); return std::__cxx_atomic_load(&__a.__a_, __order);
} }
@@ -101,6 +99,7 @@ struct __atomic_waitable_traits<atomic_flag> {
return std::addressof(__a.__a_); return std::addressof(__a.__a_);
} }
}; };
#endif // _LIBCPP_STD_VER >= 20
inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); } inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
@@ -143,43 +142,26 @@ inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, m
} }
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
__o->wait(__v); __o->wait(__v);
} }
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); }
atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT {
__o->wait(__v);
}
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void inline _LIBCPP_HIDE_FROM_ABI void
atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
__o->wait(__v, __m); __o->wait(__v, __m);
} }
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void inline _LIBCPP_HIDE_FROM_ABI void
atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
__o->wait(__v, __m); __o->wait(__v, __m);
} }
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
__o->notify_one(); inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
} inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT {
__o->notify_one();
}
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT {
__o->notify_all();
}
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT {
__o->notify_all();
}
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+29 -12
View File
@@ -19,7 +19,9 @@
#include <__assert> #include <__assert>
#include <__atomic/atomic_sync.h> #include <__atomic/atomic_sync.h>
#include <__atomic/atomic_waitable_traits.h>
#include <__atomic/check_memory_order.h> #include <__atomic/check_memory_order.h>
#include <__atomic/floating_point_helper.h>
#include <__atomic/memory_order.h> #include <__atomic/memory_order.h>
#include <__atomic/to_gcc_order.h> #include <__atomic/to_gcc_order.h>
#include <__concepts/arithmetic.h> #include <__concepts/arithmetic.h>
@@ -121,7 +123,9 @@ public:
static constexpr bool is_always_lock_free = static constexpr bool is_always_lock_free =
__atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance<required_alignment>::__instance)); __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance<required_alignment>::__instance));
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept {
return __atomic_is_lock_free(sizeof(_Tp), __ptr_);
}
_LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept _LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept
_LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) { _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) {
@@ -136,7 +140,7 @@ public:
return __desired; return __desired;
} }
_LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) { _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire ||
@@ -219,6 +223,9 @@ public:
} }
_LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); } _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); }
_LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); }
# if _LIBCPP_STD_VER >= 26
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp* address() const noexcept { return __ptr_; }
# endif
protected: protected:
using _Aligned_Tp [[__gnu__::__aligned__(required_alignment), __gnu__::__nodebug__]] = _Tp; using _Aligned_Tp [[__gnu__::__aligned__(required_alignment), __gnu__::__nodebug__]] = _Tp;
@@ -229,6 +236,8 @@ protected:
template <class _Tp> template <class _Tp>
struct __atomic_waitable_traits<__atomic_ref_base<_Tp>> { struct __atomic_waitable_traits<__atomic_ref_base<_Tp>> {
using __value_type _LIBCPP_NODEBUG = _Tp;
static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) { static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) {
return __a.load(__order); return __a.load(__order);
} }
@@ -322,20 +331,28 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
atomic_ref& operator=(const atomic_ref&) = delete; atomic_ref& operator=(const atomic_ref&) = delete;
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
_Tp __old = this->load(memory_order_relaxed); if constexpr (std::__has_rmw_builtin<_Tp>()) {
_Tp __new = __old + __arg; return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order));
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { } else {
__new = __old + __arg; _Tp __old = this->load(memory_order_relaxed);
_Tp __new = __old + __arg;
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) {
__new = __old + __arg;
}
return __old;
} }
return __old;
} }
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
_Tp __old = this->load(memory_order_relaxed); if constexpr (std::__has_rmw_builtin<_Tp>()) {
_Tp __new = __old - __arg; return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order));
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { } else {
__new = __old - __arg; _Tp __old = this->load(memory_order_relaxed);
_Tp __new = __old - __arg;
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) {
__new = __old - __arg;
}
return __old;
} }
return __old;
} }
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; }
+126 -54
View File
@@ -9,6 +9,7 @@
#ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_H #ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_H
#define _LIBCPP___ATOMIC_ATOMIC_SYNC_H #define _LIBCPP___ATOMIC_ATOMIC_SYNC_H
#include <__atomic/atomic_waitable_traits.h>
#include <__atomic/contention_t.h> #include <__atomic/contention_t.h>
#include <__atomic/memory_order.h> #include <__atomic/memory_order.h>
#include <__atomic/to_gcc_order.h> #include <__atomic/to_gcc_order.h>
@@ -19,6 +20,7 @@
#include <__type_traits/conjunction.h> #include <__type_traits/conjunction.h>
#include <__type_traits/decay.h> #include <__type_traits/decay.h>
#include <__type_traits/invoke.h> #include <__type_traits/invoke.h>
#include <__type_traits/is_same.h>
#include <__type_traits/void_t.h> #include <__type_traits/void_t.h>
#include <__utility/declval.h> #include <__utility/declval.h>
#include <cstring> #include <cstring>
@@ -29,50 +31,89 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
// The customisation points to enable the following functions:
// - __atomic_wait
// - __atomic_wait_unless
// - __atomic_notify_one
// - __atomic_notify_all
// Note that std::atomic<T>::wait was back-ported to C++03
// The below implementations look ugly to support C++03
template <class _Tp, class = void>
struct __atomic_waitable_traits {
template <class _AtomicWaitable>
static void __atomic_load(_AtomicWaitable&&, memory_order) = delete;
template <class _AtomicWaitable>
static void __atomic_contention_address(_AtomicWaitable&&) = delete;
};
template <class _Tp, class = void>
struct __atomic_waitable : false_type {};
template <class _Tp>
struct __atomic_waitable< _Tp,
__void_t<decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(
std::declval<const _Tp&>(), std::declval<memory_order>())),
decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
std::declval<const _Tp&>()))> > : true_type {};
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
# if _LIBCPP_HAS_THREADS # if _LIBCPP_HAS_THREADS
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT; # if !_LIBCPP_AVAILABILITY_HAS_NEW_SYNC
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
__libcpp_atomic_monitor(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__libcpp_atomic_wait(void const volatile*, __cxx_contention_t) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void // old dylib interface kept for backwards compatibility
__cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*) _NOEXCEPT;
__cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t) _NOEXCEPT;
_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void _LIBCPP_EXPORTED_FROM_ABI void
__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t) _NOEXCEPT; __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t) _NOEXCEPT;
# endif // !_LIBCPP_AVAILABILITY_HAS_NEW_SYNC
// new dylib interface
// return the global contention state's current value for the address
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
__atomic_monitor_global(void const* __address) _NOEXCEPT;
// wait on the global contention state to be changed from the given value for the address
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__atomic_wait_global_table(void const* __address, __cxx_contention_t __monitor_value) _NOEXCEPT;
// notify one waiter waiting on the global contention state for the address
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_one_global_table(void const*) _NOEXCEPT;
// notify all waiters waiting on the global contention state for the address
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_all_global_table(void const*) _NOEXCEPT;
// wait on the address directly with the native platform wait
template <std::size_t _Size>
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__atomic_wait_native(void const* __address, void const* __old_value) _NOEXCEPT;
// notify one waiter waiting on the address directly with the native platform wait
template <std::size_t _Size>
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_one_native(const void*) _NOEXCEPT;
// notify all waiters waiting on the address directly with the native platform wait
template <std::size_t _Size>
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_all_native(const void*) _NOEXCEPT;
# if _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
template <class _AtomicWaitable, class _Poll>
struct __atomic_wait_backoff_impl {
const _AtomicWaitable& __a_;
_Poll __poll_;
memory_order __order_;
using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
using __value_type _LIBCPP_NODEBUG = typename __waitable_traits::__value_type;
_LIBCPP_HIDE_FROM_ABI __backoff_results operator()(chrono::nanoseconds __elapsed) const {
if (__elapsed > chrono::microseconds(4)) {
auto __contention_address = const_cast<const void*>(
static_cast<const volatile void*>(__waitable_traits::__atomic_contention_address(__a_)));
if constexpr (__has_native_atomic_wait<__value_type>) {
auto __atomic_value = __waitable_traits::__atomic_load(__a_, __order_);
if (__poll_(__atomic_value))
return __backoff_results::__poll_success;
std::__atomic_wait_native<sizeof(__value_type)>(__contention_address, std::addressof(__atomic_value));
} else {
__cxx_contention_t __monitor_val = std::__atomic_monitor_global(__contention_address);
auto __atomic_value = __waitable_traits::__atomic_load(__a_, __order_);
if (__poll_(__atomic_value))
return __backoff_results::__poll_success;
std::__atomic_wait_global_table(__contention_address, __monitor_val);
}
} else {
} // poll
return __backoff_results::__continue_poll;
}
};
# else // _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
template <class _AtomicWaitable, class _Poll> template <class _AtomicWaitable, class _Poll>
struct __atomic_wait_backoff_impl { struct __atomic_wait_backoff_impl {
@@ -82,7 +123,6 @@ struct __atomic_wait_backoff_impl {
using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >; using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
_LIBCPP_AVAILABILITY_SYNC
_LIBCPP_HIDE_FROM_ABI bool _LIBCPP_HIDE_FROM_ABI bool
__update_monitor_val_and_poll(__cxx_atomic_contention_t const volatile*, __cxx_contention_t& __monitor_val) const { __update_monitor_val_and_poll(__cxx_atomic_contention_t const volatile*, __cxx_contention_t& __monitor_val) const {
// In case the contention type happens to be __cxx_atomic_contention_t, i.e. __cxx_atomic_impl<int64_t>, // In case the contention type happens to be __cxx_atomic_contention_t, i.e. __cxx_atomic_impl<int64_t>,
@@ -95,7 +135,6 @@ struct __atomic_wait_backoff_impl {
return __poll_(__monitor_val); return __poll_(__monitor_val);
} }
_LIBCPP_AVAILABILITY_SYNC
_LIBCPP_HIDE_FROM_ABI bool _LIBCPP_HIDE_FROM_ABI bool
__update_monitor_val_and_poll(void const volatile* __contention_address, __cxx_contention_t& __monitor_val) const { __update_monitor_val_and_poll(void const volatile* __contention_address, __cxx_contention_t& __monitor_val) const {
// In case the contention type is anything else, platform wait is monitoring a __cxx_atomic_contention_t // In case the contention type is anything else, platform wait is monitoring a __cxx_atomic_contention_t
@@ -105,20 +144,21 @@ struct __atomic_wait_backoff_impl {
return __poll_(__current_val); return __poll_(__current_val);
} }
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI __backoff_results operator()(chrono::nanoseconds __elapsed) const {
_LIBCPP_HIDE_FROM_ABI bool operator()(chrono::nanoseconds __elapsed) const {
if (__elapsed > chrono::microseconds(4)) { if (__elapsed > chrono::microseconds(4)) {
auto __contention_address = __waitable_traits::__atomic_contention_address(__a_); auto __contention_address = __waitable_traits::__atomic_contention_address(__a_);
__cxx_contention_t __monitor_val; __cxx_contention_t __monitor_val;
if (__update_monitor_val_and_poll(__contention_address, __monitor_val)) if (__update_monitor_val_and_poll(__contention_address, __monitor_val))
return true; return __backoff_results::__poll_success;
std::__libcpp_atomic_wait(__contention_address, __monitor_val); std::__libcpp_atomic_wait(__contention_address, __monitor_val);
} else { } else {
} // poll } // poll
return false; return __backoff_results::__continue_poll;
} }
}; };
# endif // _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
// The semantics of this function are similar to `atomic`'s // The semantics of this function are similar to `atomic`'s
// `.wait(T old, std::memory_order order)`, but instead of having a hardcoded // `.wait(T old, std::memory_order order)`, but instead of having a hardcoded
// predicate (is the loaded value unequal to `old`?), the predicate function is // predicate (is the loaded value unequal to `old`?), the predicate function is
@@ -128,9 +168,8 @@ struct __atomic_wait_backoff_impl {
// `false`, it must set the argument to its current understanding of the atomic // `false`, it must set the argument to its current understanding of the atomic
// value. The predicate function must not return `false` spuriously. // value. The predicate function must not return `false` spuriously.
template <class _AtomicWaitable, class _Poll> template <class _AtomicWaitable, class _Poll>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& __poll) {
__atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& __poll) { static_assert(__atomic_waitable<_AtomicWaitable>);
static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
__atomic_wait_backoff_impl<_AtomicWaitable, __decay_t<_Poll> > __backoff_fn = {__a, __poll, __order}; __atomic_wait_backoff_impl<_AtomicWaitable, __decay_t<_Poll> > __backoff_fn = {__a, __poll, __order};
std::__libcpp_thread_poll_with_backoff( std::__libcpp_thread_poll_with_backoff(
/* poll */ /* poll */
@@ -141,18 +180,52 @@ __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& _
/* backoff */ __backoff_fn); /* backoff */ __backoff_fn);
} }
# if _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
template <class _AtomicWaitable> template <class _AtomicWaitable>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) { _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
static_assert(__atomic_waitable<_AtomicWaitable>::value, ""); static_assert(__atomic_waitable<_AtomicWaitable>);
using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__value_type;
using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
auto __contention_address =
const_cast<const void*>(static_cast<const volatile void*>(__waitable_traits::__atomic_contention_address(__a)));
if constexpr (__has_native_atomic_wait<__value_type>) {
std::__atomic_notify_one_native<sizeof(__value_type)>(__contention_address);
} else {
std::__atomic_notify_one_global_table(__contention_address);
}
}
template <class _AtomicWaitable>
_LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
static_assert(__atomic_waitable<_AtomicWaitable>);
using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__value_type;
using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
auto __contention_address =
const_cast<const void*>(static_cast<const volatile void*>(__waitable_traits::__atomic_contention_address(__a)));
if constexpr (__has_native_atomic_wait<__value_type>) {
std::__atomic_notify_all_native<sizeof(__value_type)>(__contention_address);
} else {
std::__atomic_notify_all_global_table(__contention_address);
}
}
# else // _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
template <class _AtomicWaitable>
_LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
static_assert(__atomic_waitable<_AtomicWaitable>);
std::__cxx_atomic_notify_one(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a)); std::__cxx_atomic_notify_one(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
} }
template <class _AtomicWaitable> template <class _AtomicWaitable>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) { _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
static_assert(__atomic_waitable<_AtomicWaitable>::value, ""); static_assert(__atomic_waitable<_AtomicWaitable>);
std::__cxx_atomic_notify_all(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a)); std::__cxx_atomic_notify_all(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
} }
# endif
# else // _LIBCPP_HAS_THREADS # else // _LIBCPP_HAS_THREADS
template <class _AtomicWaitable, class _Poll> template <class _AtomicWaitable, class _Poll>
@@ -180,9 +253,8 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp c
} }
template <class _AtomicWaitable, class _Tp> template <class _AtomicWaitable, class _Tp>
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void __atomic_wait(_AtomicWaitable& __a, _Tp __val, memory_order __order) {
__atomic_wait(_AtomicWaitable& __a, _Tp __val, memory_order __order) { static_assert(__atomic_waitable<_AtomicWaitable>);
static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
std::__atomic_wait_unless(__a, __order, [&](_Tp const& __current) { std::__atomic_wait_unless(__a, __order, [&](_Tp const& __current) {
return !std::__cxx_nonatomic_compare_equal(__current, __val); return !std::__cxx_nonatomic_compare_equal(__current, __val);
}); });
+144
View File
@@ -0,0 +1,144 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_TIMED_H
#define _LIBCPP___ATOMIC_ATOMIC_SYNC_TIMED_H
#include <__atomic/atomic_waitable_traits.h>
#include <__atomic/contention_t.h>
#include <__atomic/memory_order.h>
#include <__atomic/to_gcc_order.h>
#include <__chrono/duration.h>
#include <__config>
#include <__memory/addressof.h>
#include <__thread/poll_with_backoff.h>
#include <__thread/timed_backoff_policy.h>
#include <__type_traits/conjunction.h>
#include <__type_traits/decay.h>
#include <__type_traits/has_unique_object_representation.h>
#include <__type_traits/invoke.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_copyable.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
#include <cstdint>
#include <cstring>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
_LIBCPP_AVAILABILITY_NEW_SYNC
_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __atomic_monitor_global(void const* __address) _NOEXCEPT;
// wait on the global contention state to be changed from the given value for the address
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_wait_global_table_with_timeout(
void const* __address, __cxx_contention_t __monitor_value, uint64_t __timeout_ns) _NOEXCEPT;
// wait on the address directly with the native platform wait
template <std::size_t _Size>
_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__atomic_wait_native_with_timeout(void const* __address, void const* __old_value, uint64_t __timeout_ns) _NOEXCEPT;
template <class _AtomicWaitable, class _Poll, class _Rep, class _Period>
struct __atomic_wait_timed_backoff_impl {
const _AtomicWaitable& __a_;
_Poll __poll_;
memory_order __order_;
chrono::duration<_Rep, _Period> __rel_time_;
using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
using __value_type _LIBCPP_NODEBUG = typename __waitable_traits::__value_type;
_LIBCPP_HIDE_FROM_ABI __backoff_results operator()(chrono::nanoseconds __elapsed) const {
if (__elapsed > chrono::microseconds(4)) {
auto __contention_address = const_cast<const void*>(
static_cast<const volatile void*>(__waitable_traits::__atomic_contention_address(__a_)));
uint64_t __timeout_ns =
static_cast<uint64_t>((chrono::duration_cast<chrono::nanoseconds>(__rel_time_) - __elapsed).count());
if constexpr (__has_native_atomic_wait<__value_type>) {
auto __atomic_value = __waitable_traits::__atomic_load(__a_, __order_);
if (__poll_(__atomic_value))
return __backoff_results::__poll_success;
std::__atomic_wait_native_with_timeout<sizeof(__value_type)>(
__contention_address, std::addressof(__atomic_value), __timeout_ns);
} else {
__cxx_contention_t __monitor_val = std::__atomic_monitor_global(__contention_address);
auto __atomic_value = __waitable_traits::__atomic_load(__a_, __order_);
if (__poll_(__atomic_value))
return __backoff_results::__poll_success;
std::__atomic_wait_global_table_with_timeout(__contention_address, __monitor_val, __timeout_ns);
}
} else {
} // poll
return __backoff_results::__continue_poll;
}
};
// The semantics of this function are similar to `atomic`'s
// `.wait(T old, std::memory_order order)` with a timeout, but instead of having a hardcoded
// predicate (is the loaded value unequal to `old`?), the predicate function is
// specified as an argument. The loaded value is given as an in-out argument to
// the predicate. If the predicate function returns `true`,
// `__atomic_wait_unless_with_timeout` will return. If the predicate function returns
// `false`, it must set the argument to its current understanding of the atomic
// value. The predicate function must not return `false` spuriously.
template <class _AtomicWaitable, class _Poll, class _Rep, class _Period>
_LIBCPP_HIDE_FROM_ABI bool __atomic_wait_unless_with_timeout(
const _AtomicWaitable& __a,
memory_order __order,
_Poll&& __poll,
chrono::duration<_Rep, _Period> const& __rel_time) {
static_assert(__atomic_waitable<_AtomicWaitable>, "");
__atomic_wait_timed_backoff_impl<_AtomicWaitable, __decay_t<_Poll>, _Rep, _Period> __backoff_fn = {
__a, __poll, __order, __rel_time};
auto __poll_result = std::__libcpp_thread_poll_with_backoff(
/* poll */
[&]() {
auto __current_val = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_load(__a, __order);
return __poll(__current_val);
},
/* backoff */ __backoff_fn,
__rel_time);
return __poll_result == __poll_with_backoff_results::__poll_success;
}
# elif _LIBCPP_HAS_THREADS // _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
template <class _AtomicWaitable, class _Poll, class _Rep, class _Period>
_LIBCPP_HIDE_FROM_ABI bool __atomic_wait_unless_with_timeout(
const _AtomicWaitable& __a,
memory_order __order,
_Poll&& __poll,
chrono::duration<_Rep, _Period> const& __rel_time) {
auto __res = std::__libcpp_thread_poll_with_backoff(
/* poll */
[&]() {
auto __current_val = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_load(__a, __order);
return __poll(__current_val);
},
/* backoff */ __libcpp_timed_backoff_policy(),
__rel_time);
return __res == __poll_with_backoff_results::__poll_success;
}
# endif // _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
#endif // C++20
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ATOMIC_ATOMIC_SYNC_TIMED_H
+103
View File
@@ -0,0 +1,103 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
#define _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
#include <__atomic/contention_t.h>
#include <__atomic/memory_order.h>
#include <__config>
#include <__type_traits/decay.h>
#include <__type_traits/has_unique_object_representation.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_copyable.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
#include <cstring>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
// The customisation points to enable the following functions:
// - __atomic_wait
// - __atomic_wait_unless
// - __atomic_notify_one
// - __atomic_notify_all
template <class _Tp, class = void>
struct __atomic_waitable_traits {
using __value_type _LIBCPP_NODEBUG = void;
template <class _AtomicWaitable>
static void __atomic_load(_AtomicWaitable&&, memory_order) = delete;
template <class _AtomicWaitable>
static void __atomic_contention_address(_AtomicWaitable&&) = delete;
};
template <class _Tp>
concept __atomic_waitable = requires(const _Tp __t, memory_order __order) {
typename __atomic_waitable_traits<__decay_t<_Tp> >::__value_type;
{ __atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(__t, __order) };
{ __atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(__t) };
};
# ifdef __linux__
# define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(4)
# elif defined(__APPLE__)
# define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) \
_APPLY(4) \
_APPLY(8)
# elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
# define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
# elif defined(_WIN32)
# define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
# else
# define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(sizeof(__cxx_contention_t))
# endif // __linux__
// concepts defines the types are supported natively by the platform's wait
# if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool __has_native_atomic_wait_impl() {
if (alignof(_Tp) % sizeof(_Tp) != 0)
return false;
switch (sizeof(_Tp)) {
# define _LIBCPP_MAKE_CASE(n) \
case n: \
return true;
_LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_LIBCPP_MAKE_CASE)
default:
return false;
# undef _LIBCPP_MAKE_CASE
};
}
template <class _Tp>
concept __has_native_atomic_wait =
has_unique_object_representations_v<_Tp> && is_trivially_copyable_v<_Tp> &&
std::__has_native_atomic_wait_impl<_Tp>();
# else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
template <class _Tp>
concept __has_native_atomic_wait = is_same_v<_Tp, __cxx_contention_t>;
# endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
#endif // C++20
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
+27 -3
View File
@@ -19,11 +19,35 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) // The original definition of `__cxx_contention_t` seemed a bit arbitrary.
// When we enable the _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE ABI,
// use definitions that are based on what the underlying platform supports
// instead.
#if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
# ifdef __linux__
using __cxx_contention_t _LIBCPP_NODEBUG = int32_t; using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
#else # elif defined(__APPLE__)
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t; using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
#endif // __linux__ || (_AIX && !__64BIT__) # elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
# elif defined(_AIX) && !defined(__64BIT__)
using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
# elif defined(_WIN32)
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
# else
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
# endif // __linux__
#else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
# if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__))
using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
# else
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
# endif // __linux__ || (_AIX && !__64BIT__)
#endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
using __cxx_atomic_contention_t _LIBCPP_NODEBUG = __cxx_atomic_impl<__cxx_contention_t>; using __cxx_atomic_contention_t _LIBCPP_NODEBUG = __cxx_atomic_impl<__cxx_contention_t>;
+55
View File
@@ -0,0 +1,55 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ATOMIC_FLOATING_POINT_HELPER_H
#define _LIBCPP___ATOMIC_FLOATING_POINT_HELPER_H
#include <__config>
#include <__type_traits/is_floating_point.h>
#include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool __is_fp80_long_double() {
// Only x87-fp80 long double has 64-bit mantissa
return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool __has_rmw_builtin() {
static_assert(std::is_floating_point_v<_Tp>);
# ifndef _LIBCPP_COMPILER_CLANG_BASED
return false;
# else
// The builtin __cxx_atomic_fetch_add errors during compilation for
// long double on platforms with fp80 format.
// For more details, see
// lib/Sema/SemaChecking.cpp function IsAllowedValueType
// LLVM Parser does not allow atomicrmw with x86_fp80 type.
// if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
// &Context.getTargetInfo().getLongDoubleFormat() ==
// &llvm::APFloat::x87DoubleExtended())
// For more info
// https://llvm.org/PR68602
// https://reviews.llvm.org/D53965
return !std::__is_fp80_long_double<_Tp>();
# endif
}
#endif
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ATOMIC_FLOATING_POINT_HELPER_H
+1 -2
View File
@@ -24,7 +24,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp> template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT {
static_assert(__is_unsigned_integer_v<_Tp>, "__countl_zero requires an unsigned integer type");
return __builtin_clzg(__t, numeric_limits<_Tp>::digits); return __builtin_clzg(__t, numeric_limits<_Tp>::digits);
} }
@@ -37,7 +36,7 @@ template <__unsigned_integer _Tp>
template <__unsigned_integer _Tp> template <__unsigned_integer _Tp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept {
return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; return std::countl_zero(static_cast<_Tp>(~__t));
} }
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+1 -2
View File
@@ -24,7 +24,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp> template <class _Tp>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT {
static_assert(__is_unsigned_integer_v<_Tp>, "__countr_zero only works with unsigned types");
return __builtin_ctzg(__t, numeric_limits<_Tp>::digits); return __builtin_ctzg(__t, numeric_limits<_Tp>::digits);
} }
@@ -37,7 +36,7 @@ template <__unsigned_integer _Tp>
template <__unsigned_integer _Tp> template <__unsigned_integer _Tp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept {
return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; return std::countr_zero(static_cast<_Tp>(~__t));
} }
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+1 -1
View File
@@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <__unsigned_integer _Tp> template <__unsigned_integer _Tp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept {
return __t != 0 && (((__t & (__t - 1)) == 0)); return __builtin_popcountg(__t) == 1;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
-1
View File
@@ -23,7 +23,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp> template <class _Tp>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount(_Tp __t) _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount(_Tp __t) _NOEXCEPT {
static_assert(__is_unsigned_integer_v<_Tp>, "__popcount only works with unsigned types");
return __builtin_popcountg(__t); return __builtin_popcountg(__t);
} }
+20 -31
View File
@@ -22,46 +22,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// Writing two full functions for rotl and rotr makes it easier for the compiler // Writing two full functions for rotl and rotr makes it easier for the compiler
// to optimize the code. On x86 this function becomes the ROL instruction and // to optimize the code. On x86 this function becomes the ROL instruction and
// the rotr function becomes the ROR instruction. // the rotr function becomes the ROR instruction.
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) _NOEXCEPT {
static_assert(__is_unsigned_integer_v<_Tp>, "__rotl requires an unsigned integer type");
const int __n = numeric_limits<_Tp>::digits;
int __r = __s % __n;
if (__r == 0)
return __x;
if (__r > 0)
return (__x << __r) | (__x >> (__n - __r));
return (__x >> -__r) | (__x << (__n + __r));
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) _NOEXCEPT {
static_assert(__is_unsigned_integer_v<_Tp>, "__rotr requires an unsigned integer type");
const int __n = numeric_limits<_Tp>::digits;
int __r = __s % __n;
if (__r == 0)
return __x;
if (__r > 0)
return (__x >> __r) | (__x << (__n - __r));
return (__x << -__r) | (__x >> (__n + __r));
}
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
template <__unsigned_integer _Tp> template <__unsigned_integer _Tp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept {
return std::__rotl(__t, __cnt); const int __n = numeric_limits<_Tp>::digits;
int __r = __cnt % __n;
if (__r == 0)
return __t;
if (__r > 0)
return (__t << __r) | (__t >> (__n - __r));
return (__t >> -__r) | (__t << (__n + __r));
} }
template <__unsigned_integer _Tp> template <__unsigned_integer _Tp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, int __cnt) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, int __cnt) noexcept {
return std::__rotr(__t, __cnt); const int __n = numeric_limits<_Tp>::digits;
int __r = __cnt % __n;
if (__r == 0)
return __t;
if (__r > 0)
return (__t >> __r) | (__t << (__n - __r));
return (__t << -__r) | (__t >> (__n + __r));
} }
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+207 -18
View File
@@ -15,8 +15,10 @@
#include <__algorithm/copy_backward.h> #include <__algorithm/copy_backward.h>
#include <__algorithm/copy_n.h> #include <__algorithm/copy_n.h>
#include <__algorithm/equal.h> #include <__algorithm/equal.h>
#include <__algorithm/fill_n.h>
#include <__algorithm/min.h> #include <__algorithm/min.h>
#include <__algorithm/rotate.h> #include <__algorithm/rotate.h>
#include <__algorithm/specialized_algorithms.h>
#include <__algorithm/swap_ranges.h> #include <__algorithm/swap_ranges.h>
#include <__assert> #include <__assert>
#include <__bit/countr.h> #include <__bit/countr.h>
@@ -137,7 +139,7 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator bool() const _NOEXCEPT {
return static_cast<bool>(*__seg_ & __mask_); return static_cast<bool>(*__seg_ & __mask_);
} }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator~() const _NOEXCEPT {
return !static_cast<bool>(*this); return !static_cast<bool>(*this);
} }
@@ -307,6 +309,15 @@ public:
{ {
} }
#ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
template <bool _IsConstDep = _IsConst, __enable_if_t<_IsConstDep, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT
: __seg_(__it.__seg_),
__ctz_(__it.__ctz_) {}
_LIBCPP_HIDE_FROM_ABI __bit_iterator(const __bit_iterator&) = default;
_LIBCPP_HIDE_FROM_ABI __bit_iterator& operator=(const __bit_iterator&) = default;
#else
// When _IsConst=false, this is the copy constructor. // When _IsConst=false, this is the copy constructor.
// It is non-trivial. Making it trivial would break ABI. // It is non-trivial. Making it trivial would break ABI.
// When _IsConst=true, this is a converting constructor; // When _IsConst=true, this is a converting constructor;
@@ -327,6 +338,7 @@ public:
__ctz_ = __it.__ctz_; __ctz_ = __it.__ctz_;
return *this; return *this;
} }
#endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT {
_LIBCPP_ASSERT_INTERNAL(__ctz_ < __bits_per_word, "Dereferencing an invalid __bit_iterator."); _LIBCPP_ASSERT_INTERNAL(__ctz_ < __bits_per_word, "Dereferencing an invalid __bit_iterator.");
@@ -467,20 +479,6 @@ private:
template <class _Dp> template <class _Dp>
friend struct __bit_array; friend struct __bit_array;
template <bool _FillVal, class _Dp>
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend void
__fill_n_bool(__bit_iterator<_Dp, false> __first, typename __size_difference_type_traits<_Dp>::size_type __n);
template <class _Dp, bool _IC>
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned(
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
template <class _Dp, bool _IC>
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned(
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
template <class _Dp, bool _IC>
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, _IC>, __bit_iterator<_Dp, false> >
__copy_impl::operator()(
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result) const;
template <class _Dp, bool _IC> template <class _Dp, bool _IC>
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned( _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned(
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
@@ -511,10 +509,20 @@ private:
bool _IsConst1, bool _IsConst1,
bool _IsConst2, bool _IsConst2,
class _BinaryPredicate, class _BinaryPredicate,
__enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>, int> > class _Proj1,
class _Proj2,
__enable_if_t<__is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>,
int> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_iter_impl( _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_iter_impl(
__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>, _BinaryPredicate); __bit_iterator<_Dp, _IsConst1>,
template <class _Dp, __bit_iterator<_Dp, _IsConst1>,
__bit_iterator<_Dp, _IsConst2>,
_BinaryPredicate,
_Proj1&,
_Proj2&);
template <bool,
class _Dp,
bool _IsConst1, bool _IsConst1,
bool _IsConst2, bool _IsConst2,
class _Pred, class _Pred,
@@ -537,6 +545,187 @@ private:
template <bool _ToCount, class _Dp, bool _IC> template <bool _ToCount, class _Dp, bool _IC>
friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
__count_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type); __count_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type);
template <class, class...>
friend struct __specialized_algorithm;
};
template <class _Cp>
struct __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<__bit_iterator<_Cp, false> > > {
static const bool __has_algorithm = true;
template <bool _FillVal>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
__impl(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {
using _It = __bit_iterator<_Cp, false>;
using __storage_type = typename _It::__storage_type;
const int __bits_per_word = _It::__bits_per_word;
// do first partial word
if (__first.__ctz_ != 0) {
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
__storage_type __dn = std::min(__clz_f, __n);
std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
__n -= __dn;
++__first.__seg_;
}
// do middle whole words
__storage_type __nw = __n / __bits_per_word;
std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
__n -= __nw * __bits_per_word;
// do last partial word
if (__n > 0) {
__first.__seg_ += __nw;
std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
}
}
template <class _Size, class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static __bit_iterator<_Cp, false>
operator()(__bit_iterator<_Cp, false> __first, _Size __n, const _Tp& __value) {
if (__n > 0) {
if (__value)
__impl<true>(__first, __n);
else
__impl<false>(__first, __n);
}
return __first + __n;
}
};
template <class _Cp, bool _IsConst>
struct __specialized_algorithm<_Algorithm::__copy,
__iterator_pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, _IsConst> >,
__single_iterator<__bit_iterator<_Cp, false> > > {
static const bool __has_algorithm = true;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static __bit_iterator<_Cp, false>
__aligned_impl(__bit_iterator<_Cp, _IsConst> __first,
__bit_iterator<_Cp, _IsConst> __last,
__bit_iterator<_Cp, false> __result) {
using _In = __bit_iterator<_Cp, _IsConst>;
using difference_type = typename _In::difference_type;
using __storage_type = typename _In::__storage_type;
const int __bits_per_word = _In::__bits_per_word;
difference_type __n = __last - __first;
if (__n > 0) {
// do first word
if (__first.__ctz_ != 0) {
unsigned __clz = __bits_per_word - __first.__ctz_;
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
__n -= __dn;
__storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first.__ctz_);
__storage_type __b = *__first.__seg_ & __m;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b;
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
++__first.__seg_;
// __first.__ctz_ = 0;
}
// __first.__ctz_ == 0;
// do middle words
__storage_type __nw = __n / __bits_per_word;
std::copy(std::__to_address(__first.__seg_),
std::__to_address(__first.__seg_ + __nw),
std::__to_address(__result.__seg_));
__n -= __nw * __bits_per_word;
__result.__seg_ += __nw;
// do last word
if (__n > 0) {
__first.__seg_ += __nw;
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
__storage_type __b = *__first.__seg_ & __m;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b;
__result.__ctz_ = static_cast<unsigned>(__n);
}
}
return __result;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static __bit_iterator<_Cp, false>
__unaligned_impl(__bit_iterator<_Cp, _IsConst> __first,
__bit_iterator<_Cp, _IsConst> __last,
__bit_iterator<_Cp, false> __result) {
using _In = __bit_iterator<_Cp, _IsConst>;
using difference_type = typename _In::difference_type;
using __storage_type = typename _In::__storage_type;
const int __bits_per_word = _In::__bits_per_word;
difference_type __n = __last - __first;
if (__n > 0) {
// do first word
if (__first.__ctz_ != 0) {
unsigned __clz_f = __bits_per_word - __first.__ctz_;
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
__n -= __dn;
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
__storage_type __b = *__first.__seg_ & __m;
unsigned __clz_r = __bits_per_word - __result.__ctz_;
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
__m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __result.__ctz_);
*__result.__seg_ &= ~__m;
if (__result.__ctz_ > __first.__ctz_)
*__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
else
*__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
__dn -= __ddn;
if (__dn > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __dn);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
__result.__ctz_ = static_cast<unsigned>(__dn);
}
++__first.__seg_;
// __first.__ctz_ = 0;
}
// __first.__ctz_ == 0;
// do middle words
unsigned __clz_r = __bits_per_word - __result.__ctz_;
__storage_type __m = std::__leading_mask<__storage_type>(__result.__ctz_);
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
__storage_type __b = *__first.__seg_;
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b << __result.__ctz_;
++__result.__seg_;
*__result.__seg_ &= __m;
*__result.__seg_ |= __b >> __clz_r;
}
// do last word
if (__n > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
__storage_type __b = *__first.__seg_ & __m;
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
__m = std::__middle_mask<__storage_type>(__clz_r - __dn, __result.__ctz_);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b << __result.__ctz_;
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
__n -= __dn;
if (__n > 0) {
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
*__result.__seg_ &= ~__m;
*__result.__seg_ |= __b >> __dn;
__result.__ctz_ = static_cast<unsigned>(__n);
}
}
}
return __result;
}
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 static pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
operator()(__bit_iterator<_Cp, _IsConst> __first,
__bit_iterator<_Cp, _IsConst> __last,
__bit_iterator<_Cp, false> __result) {
if (__first.__ctz_ == __result.__ctz_)
return std::make_pair(__last, __aligned_impl(__first, __last, __result));
return std::make_pair(__last, __unaligned_impl(__first, __last, __result));
}
}; };
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+1 -1
View File
@@ -18,8 +18,8 @@
#include <__memory/addressof.h> #include <__memory/addressof.h>
#include <__system_error/errc.h> #include <__system_error/errc.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_integral.h> #include <__type_traits/is_integral.h>
#include <__type_traits/is_signed.h>
#include <__type_traits/is_unsigned.h> #include <__type_traits/is_unsigned.h>
#include <__type_traits/make_unsigned.h> #include <__type_traits/make_unsigned.h>
#include <limits> #include <limits>
+1 -1
View File
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
struct _LIBCPP_EXPORTED_FROM_ABI from_chars_result { struct from_chars_result {
const char* ptr; const char* ptr;
errc ec; errc ec;
# if _LIBCPP_STD_VER >= 20 # if _LIBCPP_STD_VER >= 20
+1
View File
@@ -24,6 +24,7 @@
#include <__type_traits/integral_constant.h> #include <__type_traits/integral_constant.h>
#include <__type_traits/is_integral.h> #include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h> #include <__type_traits/is_same.h>
#include <__type_traits/is_signed.h>
#include <__type_traits/make_32_64_or_128_bit.h> #include <__type_traits/make_32_64_or_128_bit.h>
#include <__type_traits/make_unsigned.h> #include <__type_traits/make_unsigned.h>
#include <__utility/unreachable.h> #include <__utility/unreachable.h>
+1 -1
View File
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result { struct to_chars_result {
char* ptr; char* ptr;
errc ec; errc ec;
# if _LIBCPP_STD_VER >= 20 # if _LIBCPP_STD_VER >= 20
+3 -24
View File
@@ -113,31 +113,10 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__u
}; };
# endif # endif
template <typename _Tp>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) {
auto __c = __a * __b;
__r = __c;
return __c > numeric_limits<unsigned char>::max();
}
template <typename _Tp>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) {
auto __c = __a * __b;
__r = __c;
return __c > numeric_limits<unsigned short>::max();
}
template <typename _Tp>
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) {
static_assert(is_unsigned<_Tp>::value, "");
return __builtin_mul_overflow(__a, __b, std::addressof(__r));
}
template <typename _Tp, typename _Up> template <typename _Tp, typename _Up>
inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) { _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) {
return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); static_assert(is_unsigned<_Tp>::value);
return __builtin_mul_overflow(__a, static_cast<_Tp>(__b), std::addressof(__r));
} }
template <typename _Tp> template <typename _Tp>
+11
View File
@@ -13,6 +13,8 @@
#include <__chrono/duration.h> #include <__chrono/duration.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -92,6 +94,15 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr day& day::operator-=(const days& __dd) no
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::day> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::day& __d) noexcept { return static_cast<unsigned>(__d); }
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+58 -33
View File
@@ -13,6 +13,8 @@
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__compare/three_way_comparable.h> #include <__compare/three_way_comparable.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#include <__type_traits/common_type.h> #include <__type_traits/common_type.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_convertible.h> #include <__type_traits/is_convertible.h>
@@ -102,7 +104,8 @@ struct __duration_cast<_FromDuration, _ToDuration, _Period, false, false> {
}; };
template <class _ToDuration, class _Rep, class _Period, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Rep, class _Period, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration duration_cast(const duration<_Rep, _Period>& __fd) { [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration
duration_cast(const duration<_Rep, _Period>& __fd) {
return __duration_cast<duration<_Rep, _Period>, _ToDuration>()(__fd); return __duration_cast<duration<_Rep, _Period>, _ToDuration>()(__fd);
} }
@@ -117,14 +120,18 @@ inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>:
template <class _Rep> template <class _Rep>
struct duration_values { struct duration_values {
public: public:
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); }
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT { return numeric_limits<_Rep>::max(); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT { return numeric_limits<_Rep>::lowest(); } return numeric_limits<_Rep>::max();
}
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {
return numeric_limits<_Rep>::lowest();
}
}; };
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<_Rep, _Period>& __d) { [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<_Rep, _Period>& __d) {
_ToDuration __t = chrono::duration_cast<_ToDuration>(__d); _ToDuration __t = chrono::duration_cast<_ToDuration>(__d);
if (__t > __d) if (__t > __d)
__t = __t - _ToDuration{1}; __t = __t - _ToDuration{1};
@@ -132,7 +139,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<
} }
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_Rep, _Period>& __d) { [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_Rep, _Period>& __d) {
_ToDuration __t = chrono::duration_cast<_ToDuration>(__d); _ToDuration __t = chrono::duration_cast<_ToDuration>(__d);
if (__t < __d) if (__t < __d)
__t = __t + _ToDuration{1}; __t = __t + _ToDuration{1};
@@ -140,7 +147,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_
} }
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<_Rep, _Period>& __d) { [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<_Rep, _Period>& __d) {
_ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __lower = chrono::floor<_ToDuration>(__d);
_ToDuration __upper = __lower + _ToDuration{1}; _ToDuration __upper = __lower + _ToDuration{1};
auto __lower_diff = __d - __lower; auto __lower_diff = __d - __lower;
@@ -220,14 +227,14 @@ public:
// observer // observer
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR rep count() const { return __rep_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR rep count() const { return __rep_; }
// arithmetic // arithmetic
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator+() const { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator+() const {
return typename common_type<duration>::type(*this); return typename common_type<duration>::type(*this);
} }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator-() const { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator-() const {
return typename common_type<duration>::type(-__rep_); return typename common_type<duration>::type(-__rep_);
} }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator++() { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator++() {
@@ -269,13 +276,13 @@ public:
// special values // special values
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {
return duration(duration_values<rep>::zero()); return duration(duration_values<rep>::zero());
} }
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {
return duration(duration_values<rep>::min()); return duration(duration_values<rep>::min());
} }
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {
return duration(duration_values<rep>::max()); return duration(duration_values<rep>::max());
} }
}; };
@@ -389,7 +396,7 @@ operator<=>(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Perio
// Duration + // Duration +
template <class _Rep1, class _Period1, class _Rep2, class _Period2> template <class _Rep1, class _Period1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd; typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd;
@@ -399,7 +406,7 @@ operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2
// Duration - // Duration -
template <class _Rep1, class _Period1, class _Rep2, class _Period2> template <class _Rep1, class _Period1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd; typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd;
@@ -412,7 +419,8 @@ template <class _Rep1,
class _Period, class _Period,
class _Rep2, class _Rep2,
__enable_if_t<is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0> __enable_if_t<is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr; typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd; typedef duration<_Cr, _Period> _Cd;
@@ -423,7 +431,8 @@ template <class _Rep1,
class _Period, class _Period,
class _Rep2, class _Rep2,
__enable_if_t<is_convertible<const _Rep1&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0> __enable_if_t<is_convertible<const _Rep1&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) { operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) {
return __d * __s; return __d * __s;
} }
@@ -436,7 +445,8 @@ template <class _Rep1,
__enable_if_t<!__is_duration_v<_Rep2> && __enable_if_t<!__is_duration_v<_Rep2> &&
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0> int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr; typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd; typedef duration<_Cr, _Period> _Cd;
@@ -444,7 +454,7 @@ operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
} }
template <class _Rep1, class _Period1, class _Rep2, class _Period2> template <class _Rep1, class _Period1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<_Rep1, _Rep2>::type [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<_Rep1, _Rep2>::type
operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Ct; typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Ct;
return _Ct(__lhs).count() / _Ct(__rhs).count(); return _Ct(__lhs).count() / _Ct(__rhs).count();
@@ -458,7 +468,8 @@ template <class _Rep1,
__enable_if_t<!__is_duration_v<_Rep2> && __enable_if_t<!__is_duration_v<_Rep2> &&
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0> int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr; typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd; typedef duration<_Cr, _Period> _Cd;
@@ -466,7 +477,7 @@ operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
} }
template <class _Rep1, class _Period1, class _Rep2, class _Period2> template <class _Rep1, class _Period1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr; typedef typename common_type<_Rep1, _Rep2>::type _Cr;
@@ -481,51 +492,53 @@ operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2
inline namespace literals { inline namespace literals {
inline namespace chrono_literals { inline namespace chrono_literals {
_LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) {
return chrono::hours(static_cast<chrono::hours::rep>(__h)); return chrono::hours(static_cast<chrono::hours::rep>(__h));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<3600, 1>> operator""h(long double __h) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<3600, 1>>
operator""h(long double __h) {
return chrono::duration<long double, ratio<3600, 1>>(__h); return chrono::duration<long double, ratio<3600, 1>>(__h);
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) {
return chrono::minutes(static_cast<chrono::minutes::rep>(__m)); return chrono::minutes(static_cast<chrono::minutes::rep>(__m));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<60, 1>> operator""min(long double __m) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<60, 1>>
operator""min(long double __m) {
return chrono::duration<long double, ratio<60, 1>>(__m); return chrono::duration<long double, ratio<60, 1>>(__m);
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) {
return chrono::seconds(static_cast<chrono::seconds::rep>(__s)); return chrono::seconds(static_cast<chrono::seconds::rep>(__s));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double> operator""s(long double __s) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double> operator""s(long double __s) {
return chrono::duration<long double>(__s); return chrono::duration<long double>(__s);
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) {
return chrono::milliseconds(static_cast<chrono::milliseconds::rep>(__ms)); return chrono::milliseconds(static_cast<chrono::milliseconds::rep>(__ms));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, milli> operator""ms(long double __ms) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, milli> operator""ms(long double __ms) {
return chrono::duration<long double, milli>(__ms); return chrono::duration<long double, milli>(__ms);
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) {
return chrono::microseconds(static_cast<chrono::microseconds::rep>(__us)); return chrono::microseconds(static_cast<chrono::microseconds::rep>(__us));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, micro> operator""us(long double __us) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, micro> operator""us(long double __us) {
return chrono::duration<long double, micro>(__us); return chrono::duration<long double, micro>(__us);
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) {
return chrono::nanoseconds(static_cast<chrono::nanoseconds::rep>(__ns)); return chrono::nanoseconds(static_cast<chrono::nanoseconds::rep>(__ns));
} }
_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, nano> operator""ns(long double __ns) { [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, nano> operator""ns(long double __ns) {
return chrono::duration<long double, nano>(__ns); return chrono::duration<long double, nano>(__ns);
} }
@@ -538,6 +551,18 @@ using namespace literals::chrono_literals;
#endif // _LIBCPP_STD_VER >= 14 #endif // _LIBCPP_STD_VER >= 14
#if _LIBCPP_STD_VER >= 26
template <class _Rep, class _Period>
requires __has_enabled_hash<_Rep>::value
struct hash<chrono::duration<_Rep, _Period>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::duration<_Rep, _Period>& __d) {
return hash<_Rep>{}(__d.count());
}
};
#endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS _LIBCPP_POP_MACROS
+4 -2
View File
@@ -60,16 +60,18 @@ struct _FilesystemClock {
_LIBCPP_EXPORTED_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; _LIBCPP_EXPORTED_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false;
_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_EXPORTED_FROM_ABI static time_point now() noexcept; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI static time_point now() noexcept;
# if _LIBCPP_STD_VER >= 20 # if _LIBCPP_STD_VER >= 20
template <class _Duration> template <class _Duration>
[[nodiscard]]
_LIBCPP_HIDE_FROM_ABI static chrono::sys_time<_Duration> to_sys(const chrono::file_time<_Duration>& __t) { _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()); return chrono::sys_time<_Duration>(__t.time_since_epoch());
} }
template <class _Duration> template <class _Duration>
_LIBCPP_HIDE_FROM_ABI static chrono::file_time<_Duration> from_sys(const chrono::sys_time<_Duration>& __t) { [[nodiscard]] _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()); return chrono::file_time<_Duration>(__t.time_since_epoch());
} }
# endif // _LIBCPP_STD_VER >= 20 # endif // _LIBCPP_STD_VER >= 20
+72
View File
@@ -0,0 +1,72 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___CHRONO_IS_CLOCK_H
#define _LIBCPP___CHRONO_IS_CLOCK_H
#include <__config>
#include <__chrono/duration.h>
#include <__chrono/time_point.h>
#include <__concepts/same_as.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_class.h>
#include <__type_traits/is_union.h>
#include <ratio>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
#if _LIBCPP_STD_VER >= 20
_LIBCPP_BEGIN_NAMESPACE_STD
namespace chrono {
// Helper to check that _Tp::time_point has the form time_point<_, typename _Tp::duration>.
template <class _TimePoint, class _ClockType>
inline constexpr bool __is_valid_clock_time_point_v = false;
template <class _TimePointClock, class _ClockType>
inline constexpr bool
__is_valid_clock_time_point_v<time_point<_TimePointClock, typename _ClockType::duration>, _ClockType> = true;
// Check if a clock satisfies the Cpp17Clock requirements as defined in [time.clock.req]
template <class _Tp>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_clock_v = requires {
typename _Tp::rep;
requires is_arithmetic_v<typename _Tp::rep> || is_class_v<typename _Tp::rep> || is_union_v<typename _Tp::rep>;
typename _Tp::period;
requires __is_ratio_v<typename _Tp::period>;
typename _Tp::duration;
requires same_as<typename _Tp::duration, duration<typename _Tp::rep, typename _Tp::period>>;
typename _Tp::time_point;
requires __is_valid_clock_time_point_v<typename _Tp::time_point, _Tp>;
_Tp::is_steady;
requires same_as<decltype((_Tp::is_steady)), const bool&>;
_Tp::now();
requires same_as<decltype(_Tp::now()), typename _Tp::time_point>;
};
template <class _Tp>
struct _LIBCPP_NO_SPECIALIZATIONS is_clock : bool_constant<is_clock_v<_Tp>> {};
} // namespace chrono
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER
#endif // _LIBCPP___CHRONO_IS_CLOCK_H
+13
View File
@@ -22,6 +22,8 @@
# include <__compare/ordering.h> # include <__compare/ordering.h>
# include <__compare/three_way_comparable.h> # include <__compare/three_way_comparable.h>
# include <__config> # include <__config>
# include <__cstddef/size_t.h>
# include <__functional/hash.h>
# include <__utility/private_constructor_tag.h> # include <__utility/private_constructor_tag.h>
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -122,6 +124,17 @@ private:
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::leap_second> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::leap_second& __lp) noexcept {
return std::__hash_combine(hash<chrono::sys_seconds>{}(__lp.date()), hash<chrono::seconds>{}(__lp.value()));
}
};
# endif // _LIBCPP_STD_VER >= 26
# endif // _LIBCPP_STD_VER >= 20 # endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+13
View File
@@ -13,6 +13,8 @@
#include <__chrono/duration.h> #include <__chrono/duration.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -108,6 +110,17 @@ inline constexpr month December{12};
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::month> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month& __m) noexcept {
return static_cast<unsigned>(__m);
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+22
View File
@@ -13,6 +13,8 @@
#include <__chrono/month.h> #include <__chrono/month.h>
#include <__chrono/weekday.h> #include <__chrono/weekday.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -98,6 +100,26 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday_last operator/(const weekda
} }
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::month_weekday> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_weekday& __mw) noexcept {
return std::__hash_combine(
hash<chrono::month>{}(__mw.month()), hash<chrono::weekday_indexed>{}(__mw.weekday_indexed()));
}
};
template <>
struct hash<chrono::month_weekday_last> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_weekday_last& __mwl) noexcept {
return std::__hash_combine(
hash<chrono::month>{}(__mwl.month()), hash<chrono::weekday_last>{}(__mwl.weekday_last()));
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+20
View File
@@ -15,6 +15,8 @@
#include <__chrono/month.h> #include <__chrono/month.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -126,6 +128,24 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr month_day_last operator/(last_spec, int _
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::month_day> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_day& __md) noexcept {
return std::__hash_combine(hash<chrono::month>{}(__md.month()), hash<chrono::day>{}(__md.day()));
}
};
template <>
struct hash<chrono::month_day_last> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_day_last& __mdl) noexcept {
return hash<chrono::month>{}(__mdl.month());
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+1 -1
View File
@@ -31,7 +31,7 @@ public:
typedef chrono::time_point<steady_clock, duration> time_point; typedef chrono::time_point<steady_clock, duration> time_point;
static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = true; static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = true;
static time_point now() _NOEXCEPT; [[__nodiscard__]] static time_point now() _NOEXCEPT;
}; };
#endif #endif
+3 -3
View File
@@ -31,9 +31,9 @@ public:
typedef chrono::time_point<system_clock> time_point; typedef chrono::time_point<system_clock> time_point;
static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false;
static time_point now() _NOEXCEPT; [[__nodiscard__]] static time_point now() _NOEXCEPT;
static time_t to_time_t(const time_point& __t) _NOEXCEPT; [[__nodiscard__]] static time_t to_time_t(const time_point& __t) _NOEXCEPT;
static time_point from_time_t(time_t __t) _NOEXCEPT; [[__nodiscard__]] static time_point from_time_t(time_t __t) _NOEXCEPT;
}; };
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
+37 -13
View File
@@ -14,6 +14,8 @@
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__compare/three_way_comparable.h> #include <__compare/three_way_comparable.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#include <__type_traits/common_type.h> #include <__type_traits/common_type.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_convertible.h> #include <__type_traits/is_convertible.h>
@@ -54,7 +56,9 @@ public:
// observer // observer
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const { return __d_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const {
return __d_;
}
// arithmetic // arithmetic
@@ -82,8 +86,12 @@ public:
// special values // special values
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT { return time_point(duration::min()); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT { return time_point(duration::max()); } return time_point(duration::min());
}
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT {
return time_point(duration::max());
}
}; };
} // namespace chrono } // namespace chrono
@@ -95,30 +103,33 @@ struct common_type<chrono::time_point<_Clock, _Duration1>, chrono::time_point<_C
namespace chrono { namespace chrono {
template <class _ToDuration, class _Clock, class _Duration> template <class _ToDuration, class _Clock, class _Duration, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, _ToDuration> [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, _ToDuration>
time_point_cast(const time_point<_Clock, _Duration>& __t) { time_point_cast(const time_point<_Clock, _Duration>& __t) {
return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch()));
} }
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) { [[nodiscard]] inline
_LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) {
return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())};
} }
template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> ceil(const time_point<_Clock, _Duration>& __t) { [[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration>
ceil(const time_point<_Clock, _Duration>& __t) {
return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())};
} }
template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0> template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> round(const time_point<_Clock, _Duration>& __t) { [[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration>
round(const time_point<_Clock, _Duration>& __t) {
return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())};
} }
template <class _Rep, class _Period, enable_if_t<numeric_limits<_Rep>::is_signed, int> = 0> template <class _Rep, class _Period, enable_if_t<numeric_limits<_Rep>::is_signed, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI constexpr duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) { [[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) {
return __d >= __d.zero() ? +__d : -__d; return __d >= __d.zero() ? +__d : -__d;
} }
#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP_STD_VER >= 17
@@ -188,7 +199,7 @@ operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock
// time_point operator+(time_point x, duration y); // time_point operator+(time_point x, duration y);
template <class _Clock, class _Duration1, class _Rep2, class _Period2> template <class _Clock, class _Duration1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { 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; typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr;
@@ -198,7 +209,7 @@ operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Pe
// time_point operator+(duration x, time_point y); // time_point operator+(duration x, time_point y);
template <class _Rep1, class _Period1, class _Clock, class _Duration2> template <class _Rep1, class _Period1, class _Clock, class _Duration2>
inline _LIBCPP_HIDE_FROM_ABI [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<duration<_Rep1, _Period1>, _Duration2>::type> _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<duration<_Rep1, _Period1>, _Duration2>::type>
operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
return __rhs + __lhs; return __rhs + __lhs;
@@ -207,7 +218,7 @@ operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Dura
// time_point operator-(time_point x, duration y); // time_point operator-(time_point x, duration y);
template <class _Clock, class _Duration1, class _Rep2, class _Period2> template <class _Clock, class _Duration1, class _Rep2, class _Period2>
inline _LIBCPP_HIDE_FROM_ABI [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { 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; typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret;
@@ -217,13 +228,26 @@ operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Pe
// duration operator-(time_point x, time_point y); // duration operator-(time_point x, time_point y);
template <class _Clock, class _Duration1, class _Duration2> template <class _Clock, class _Duration1, class _Duration2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename common_type<_Duration1, _Duration2>::type [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
typename common_type<_Duration1, _Duration2>::type
operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
return __lhs.time_since_epoch() - __rhs.time_since_epoch(); return __lhs.time_since_epoch() - __rhs.time_since_epoch();
} }
} // namespace chrono } // namespace chrono
#if _LIBCPP_STD_VER >= 26
template <class _Clock, class _Duration>
requires __has_enabled_hash<_Duration>::value
struct hash<chrono::time_point<_Clock, _Duration>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::time_point<_Clock, _Duration>& __tp) {
return hash<_Duration>{}(__tp.time_since_epoch());
}
};
#endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS _LIBCPP_POP_MACROS
+25
View File
@@ -15,6 +15,8 @@
#include <__chrono/system_clock.h> #include <__chrono/system_clock.h>
#include <__chrono/time_point.h> #include <__chrono/time_point.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -160,6 +162,29 @@ inline constexpr weekday Saturday{6};
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::weekday> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday& __w) noexcept { return __w.c_encoding(); }
};
template <>
struct hash<chrono::weekday_indexed> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday_indexed& __wi) noexcept {
return std::__hash_combine(hash<chrono::weekday>{}(__wi.weekday()), __wi.index());
}
};
template <>
struct hash<chrono::weekday_last> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday_last& __wl) noexcept {
return hash<chrono::weekday>{}(__wl.weekday());
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+11
View File
@@ -13,6 +13,8 @@
#include <__chrono/duration.h> #include <__chrono/duration.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#include <limits> #include <limits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -109,6 +111,15 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept {
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::year> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year& __y) noexcept { return static_cast<int>(__y); }
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+13
View File
@@ -15,6 +15,8 @@
#include <__chrono/year.h> #include <__chrono/year.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -116,6 +118,17 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::year_month> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month& __ym) noexcept {
return std::__hash_combine(hash<chrono::year>{}(__ym.year()), hash<chrono::month>{}(__ym.month()));
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+23
View File
@@ -21,6 +21,8 @@
#include <__chrono/year_month.h> #include <__chrono/year_month.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#include <limits> #include <limits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -330,6 +332,27 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool year_month_day::ok() const noexcept
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::year_month_day> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_day& __ymd) noexcept {
return std::__hash_combine(
hash<chrono::year>{}(__ymd.year()),
std::__hash_combine(hash<chrono::month>{}(__ymd.month()), hash<chrono::day>{}(__ymd.day())));
}
};
template <>
struct hash<chrono::year_month_day_last> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_day_last& __ymdl) noexcept {
return std::__hash_combine(
hash<chrono::year>{}(__ymdl.year()), hash<chrono::month_day_last>{}(__ymdl.month_day_last()));
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+26
View File
@@ -22,6 +22,8 @@
#include <__chrono/year_month.h> #include <__chrono/year_month.h>
#include <__chrono/year_month_day.h> #include <__chrono/year_month_day.h>
#include <__config> #include <__config>
#include <__cstddef/size_t.h>
#include <__functional/hash.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@@ -280,6 +282,30 @@ year_month_weekday_last::operator-=(const years& __dy) noexcept {
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <>
struct hash<chrono::year_month_weekday> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_weekday& __ymw) noexcept {
return std::__hash_combine(
hash<chrono::year>{}(__ymw.year()),
std::__hash_combine(
hash<chrono::month>{}(__ymw.month()), hash<chrono::weekday_indexed>{}(__ymw.weekday_indexed())));
}
};
template <>
struct hash<chrono::year_month_weekday_last> {
_LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_weekday_last& __ymwl) noexcept {
return std::__hash_combine(
hash<chrono::year>{}(__ymwl.year()),
std::__hash_combine(
hash<chrono::month>{}(__ymwl.month()), hash<chrono::weekday_last>{}(__ymwl.weekday_last())));
}
};
# endif // _LIBCPP_STD_VER >= 26
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+16
View File
@@ -24,6 +24,8 @@
# include <__chrono/tzdb_list.h> # include <__chrono/tzdb_list.h>
# include <__concepts/constructible.h> # include <__concepts/constructible.h>
# include <__config> # include <__config>
# include <__cstddef/size_t.h>
# include <__functional/hash.h>
# include <__type_traits/common_type.h> # include <__type_traits/common_type.h>
# include <__type_traits/conditional.h> # include <__type_traits/conditional.h>
# include <__type_traits/remove_cvref.h> # include <__type_traits/remove_cvref.h>
@@ -216,6 +218,20 @@ operator==(const zoned_time<_Duration1, _TimeZonePtr>& __lhs, const zoned_time<_
} // namespace chrono } // namespace chrono
# if _LIBCPP_STD_VER >= 26
template <class _Duration, class _TimeZonePtr>
requires __has_enabled_hash<_Duration>::value && __has_enabled_hash<_TimeZonePtr>::value
struct hash<chrono::zoned_time<_Duration, _TimeZonePtr>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static size_t
operator()(const chrono::zoned_time<_Duration, _TimeZonePtr>& __zt) {
return std::__hash_combine(
hash<chrono::sys_time<_Duration>>{}(__zt.get_sys_time()), hash<_TimeZonePtr>{}(__zt.get_time_zone()));
}
};
# endif // _LIBCPP_STD_VER >= 26
# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && # endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
// _LIBCPP_HAS_LOCALIZATION // _LIBCPP_HAS_LOCALIZATION
+6 -6
View File
@@ -20,12 +20,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; } [[nodiscard]] _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; } [[nodiscard]] _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; } [[nodiscard]] _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; } [[nodiscard]] _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; } [[nodiscard]] _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; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; }
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
+12 -30
View File
@@ -13,7 +13,6 @@
#include <__compare/compare_three_way.h> #include <__compare/compare_three_way.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__config> #include <__config>
#include <__math/exponential_functions.h>
#include <__math/traits.h> #include <__math/traits.h>
#include <__type_traits/conditional.h> #include <__type_traits/conditional.h>
#include <__type_traits/decay.h> #include <__type_traits/decay.h>
@@ -53,38 +52,21 @@ struct __fn {
template <class _Tp, class _Up, class _Dp = decay_t<_Tp>> template <class _Tp, class _Up, class _Dp = decay_t<_Tp>>
requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> 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 { _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)) { if constexpr (numeric_limits<_Dp>::is_iec559 &&
int32_t __rx = std::bit_cast<int32_t>(__t); (sizeof(_Dp) == sizeof(int32_t) || sizeof(_Dp) == sizeof(int64_t))) {
int32_t __ry = std::bit_cast<int32_t>(__u); using _IntT = conditional_t<sizeof(_Dp) == sizeof(int32_t), int32_t, int64_t>;
__rx = (__rx < 0) ? (numeric_limits<int32_t>::min() - __rx - 1) : __rx; _IntT __rx = std::bit_cast<_IntT>(__t);
__ry = (__ry < 0) ? (numeric_limits<int32_t>::min() - __ry - 1) : __ry; _IntT __ry = std::bit_cast<_IntT>(__u);
return (__rx <=> __ry); __rx = (__rx < 0) ? (numeric_limits<_IntT>::min() - __rx - 1) : __rx;
} else if constexpr (numeric_limits<_Dp>::is_iec559 && sizeof(_Dp) == sizeof(int64_t)) { __ry = (__ry < 0) ? (numeric_limits<_IntT>::min() - __ry - 1) : __ry;
int64_t __rx = std::bit_cast<int64_t>(__t);
int64_t __ry = std::bit_cast<int64_t>(__u);
__rx = (__rx < 0) ? (numeric_limits<int64_t>::min() - __rx - 1) : __rx;
__ry = (__ry < 0) ? (numeric_limits<int64_t>::min() - __ry - 1) : __ry;
return (__rx <=> __ry); return (__rx <=> __ry);
} else if (__t < __u) { } else if (__t < __u) {
return strong_ordering::less; return strong_ordering::less;
} else if (__t > __u) { } else if (__t > __u) {
return strong_ordering::greater; return strong_ordering::greater;
} else if (__t == __u) { } else if (__t == __u) {
if constexpr (numeric_limits<_Dp>::radix == 2) { static_assert(numeric_limits<_Dp>::radix == 2, "floating point type with a radix other than 2?");
return __math::signbit(__u) <=> __math::signbit(__t); return __math::signbit(__u) <=> __math::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 || __math::isinf(__t)) {
return __math::signbit(__u) <=> __math::signbit(__t);
} else {
int __texp, __uexp;
(void)__math::frexp(__t, &__texp);
(void)__math::frexp(__u, &__uexp);
return (__t < 0) ? (__texp <=> __uexp) : (__uexp <=> __texp);
}
}
} else { } else {
// They're unordered, so one of them must be a NAN. // They're unordered, so one of them must be a NAN.
// The order is -QNAN, -SNAN, numbers, +SNAN, +QNAN. // The order is -QNAN, -SNAN, numbers, +SNAN, +QNAN.
@@ -93,9 +75,9 @@ struct __fn {
bool __t_is_negative = __math::signbit(__t); bool __t_is_negative = __math::signbit(__t);
bool __u_is_negative = __math::signbit(__u); bool __u_is_negative = __math::signbit(__u);
using _IntType = using _IntType =
conditional_t< sizeof(__t) == sizeof(int32_t), conditional_t<sizeof(__t) == sizeof(int32_t),
int32_t, int32_t,
conditional_t< sizeof(__t) == sizeof(int64_t), int64_t, void> >; conditional_t<sizeof(__t) == sizeof(int64_t), int64_t, void>>;
if constexpr (is_same_v<_IntType, void>) { if constexpr (is_same_v<_IntType, void>) {
static_assert(sizeof(_Dp) == 0, "std::strong_order is unimplemented for this floating-point type"); static_assert(sizeof(_Dp) == 0, "std::strong_order is unimplemented for this floating-point type");
} else if (__t_is_nan && __u_is_nan) { } else if (__t_is_nan && __u_is_nan) {
+2 -2
View File
@@ -12,6 +12,7 @@
#include <__compare/common_comparison_category.h> #include <__compare/common_comparison_category.h>
#include <__compare/ordering.h> #include <__compare/ordering.h>
#include <__concepts/common_reference_with.h> #include <__concepts/common_reference_with.h>
#include <__concepts/comparison_common_type.h>
#include <__concepts/equality_comparable.h> #include <__concepts/equality_comparable.h>
#include <__concepts/same_as.h> #include <__concepts/same_as.h>
#include <__concepts/totally_ordered.h> #include <__concepts/totally_ordered.h>
@@ -39,8 +40,7 @@ concept three_way_comparable =
template <class _Tp, class _Up, class _Cat = partial_ordering> template <class _Tp, class _Up, class _Cat = partial_ordering>
concept three_way_comparable_with = concept three_way_comparable_with =
three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && __comparison_common_type_with<_Tp, _Up> &&
common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> && three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
__weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> && __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
+40
View File
@@ -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_COMPARISON_COMMON_TYPE_H
#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
#include <__concepts/convertible_to.h>
#include <__concepts/same_as.h>
#include <__config>
#include <__type_traits/common_reference.h>
#include <__type_traits/remove_cvref.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
template <class _Tp, class _Up, class _CommonRef = common_reference_t<const _Tp&, const _Up&>>
concept __comparison_common_type_with_impl =
same_as<common_reference_t<const _Tp&, const _Up&>, common_reference_t<const _Up&, const _Tp&>> && requires {
requires convertible_to<const _Tp&, const _CommonRef&> || convertible_to<_Tp, const _CommonRef&>;
requires convertible_to<const _Up&, const _CommonRef&> || convertible_to<_Up, const _CommonRef&>;
};
template <class _Tp, class _Up>
concept __comparison_common_type_with = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+2 -1
View File
@@ -11,6 +11,7 @@
#include <__concepts/boolean_testable.h> #include <__concepts/boolean_testable.h>
#include <__concepts/common_reference_with.h> #include <__concepts/common_reference_with.h>
#include <__concepts/comparison_common_type.h>
#include <__config> #include <__config>
#include <__type_traits/common_reference.h> #include <__type_traits/common_reference.h>
#include <__type_traits/make_const_lvalue_ref.h> #include <__type_traits/make_const_lvalue_ref.h>
@@ -41,7 +42,7 @@ concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
template <class _Tp, class _Up> template <class _Tp, class _Up>
concept equality_comparable_with = concept equality_comparable_with =
equality_comparable<_Tp> && equality_comparable<_Up> && equality_comparable<_Tp> && equality_comparable<_Up> &&
common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && __comparison_common_type_with<_Tp, _Up> &&
equality_comparable< equality_comparable<
common_reference_t< common_reference_t<
__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Tp>,
@@ -170,7 +170,7 @@ public:
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
typedef __libcpp_condvar_t* native_handle_type; typedef __libcpp_condvar_t* native_handle_type;
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
private: private:
void void
+63 -280
View File
@@ -14,6 +14,8 @@
#include <__configuration/abi.h> #include <__configuration/abi.h>
#include <__configuration/availability.h> #include <__configuration/availability.h>
#include <__configuration/compiler.h> #include <__configuration/compiler.h>
#include <__configuration/experimental.h>
#include <__configuration/hardening.h>
#include <__configuration/language.h> #include <__configuration/language.h>
#include <__configuration/platform.h> #include <__configuration/platform.h>
@@ -28,7 +30,7 @@
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
// defined to XXYYZZ. // defined to XXYYZZ.
# define _LIBCPP_VERSION 210100 # define _LIBCPP_VERSION 220104
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
@@ -38,195 +40,6 @@
# define _LIBCPP_FREESTANDING # define _LIBCPP_FREESTANDING
# endif # endif
// NOLINTNEXTLINE(libcpp-cpp-version-check)
# if __cplusplus < 201103L
# define _LIBCPP_CXX03_LANG
# endif
# if __has_feature(experimental_library)
# ifndef _LIBCPP_ENABLE_EXPERIMENTAL
# define _LIBCPP_ENABLE_EXPERIMENTAL
# endif
# endif
// Incomplete features get their own specific disabling flags. This makes it
// easier to grep for target specific flags once the feature is complete.
# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY)
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1
# else
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0
# endif
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
// HARDENING {
// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated.
// Since hardening went through several changes (many of which impacted user-facing macros),
// we're keeping these checks around for a bit longer than usual. Failure to properly configure
// hardening results in checks being dropped silently, which is a pretty big deal.
# if defined(_LIBCPP_ENABLE_ASSERTIONS)
# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
# endif
# if defined(_LIBCPP_ENABLE_HARDENED_MODE)
# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
# endif
# if defined(_LIBCPP_ENABLE_SAFE_MODE)
# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
# endif
# if defined(_LIBCPP_ENABLE_DEBUG_MODE)
# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
# endif
// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values:
//
// - `_LIBCPP_HARDENING_MODE_NONE`;
// - `_LIBCPP_HARDENING_MODE_FAST`;
// - `_LIBCPP_HARDENING_MODE_EXTENSIVE`;
// - `_LIBCPP_HARDENING_MODE_DEBUG`.
//
// These values have the following effects:
//
// - `_LIBCPP_HARDENING_MODE_NONE` -- sets the hardening mode to "none" which disables all runtime hardening checks;
//
// - `_LIBCPP_HARDENING_MODE_FAST` -- sets that hardening mode to "fast". The fast mode enables security-critical checks
// that can be done with relatively little runtime overhead in constant time;
//
// - `_LIBCPP_HARDENING_MODE_EXTENSIVE` -- sets the hardening mode to "extensive". The extensive mode is a superset of
// the fast mode that additionally enables checks that are relatively cheap and prevent common types of logic errors
// but are not necessarily security-critical;
//
// - `_LIBCPP_HARDENING_MODE_DEBUG` -- sets the hardening mode to "debug". The debug mode is a superset of the extensive
// mode and enables all checks available in the library, including internal assertions. Checks that are part of the
// debug mode can be very expensive and thus the debug mode is intended to be used for testing, not in production.
// Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These
// macros are only for internal use -- users should only pick one of the high-level hardening modes described above.
//
// - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and
// a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid:
// - the sentinel is reachable from the begin iterator;
// - TODO(hardening): both iterators refer to the same container.
//
// - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through
// the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access
// a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like
// `optional` and `function` are considered one-element containers for the purposes of this check.
//
// - `_LIBCPP_ASSERT_NON_NULL` -- checks that the pointer being dereferenced is not null. On most modern platforms zero
// address does not refer to an actual location in memory, so a null pointer dereference would not compromize the
// memory security of a program (however, it is still undefined behavior that can result in strange errors due to
// compiler optimizations).
//
// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the
// given ranges do not overlap.
//
// - `_LIBCPP_ASSERT_VALID_DEALLOCATION` -- checks that an attempt to deallocate memory is valid (e.g. the given object
// was allocated by the given allocator). Violating this category typically results in a memory leak.
//
// - `_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL` -- checks that a call to an external API doesn't fail in
// an unexpected manner. This includes triggering documented cases of undefined behavior in an external library (like
// attempting to unlock an unlocked mutex in pthreads). Any API external to the library falls under this category
// (from system calls to compiler intrinsics). We generally don't expect these failures to compromize memory safety or
// otherwise create an immediate security issue.
//
// - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure
// the containers have compatible allocators.
//
// - `_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN` -- checks that the given argument is within the domain of valid arguments
// for the function. Violating this typically produces an incorrect result (e.g. the clamp algorithm returns the
// original value without clamping it due to incorrect functors) or puts an object into an invalid state (e.g.
// a string view where only a subset of elements is possible to access). This category is for assertions violating
// which doesn't cause any immediate issues in the library -- whatever the consequences are, they will happen in the
// user code.
//
// - `_LIBCPP_ASSERT_PEDANTIC` -- checks prerequisites which are imposed by the Standard, but violating which happens to
// be benign in our implementation.
//
// - `_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT` -- checks that the given argument satisfies the semantic requirements imposed
// by the Standard. Typically, there is no simple way to completely prove that a semantic requirement is satisfied;
// thus, this would often be a heuristic check and it might be quite expensive.
//
// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on
// user input.
//
// - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet.
// clang-format off
# define _LIBCPP_HARDENING_MODE_NONE (1 << 1)
# define _LIBCPP_HARDENING_MODE_FAST (1 << 2)
# define _LIBCPP_HARDENING_MODE_EXTENSIVE (1 << 4) // Deliberately not ordered.
# define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3)
// clang-format on
# ifndef _LIBCPP_HARDENING_MODE
# ifndef _LIBCPP_HARDENING_MODE_DEFAULT
# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \
`__config_site` header, please make sure your installation of libc++ is not broken.
# endif
# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT
# endif
# if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && \
_LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \
_LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \
_LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
# error _LIBCPP_HARDENING_MODE must be set to one of the following values: \
_LIBCPP_HARDENING_MODE_NONE, \
_LIBCPP_HARDENING_MODE_FAST, \
_LIBCPP_HARDENING_MODE_EXTENSIVE, \
_LIBCPP_HARDENING_MODE_DEBUG
# endif
// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts
// `ignore` semantic which wouldn't evaluate the assertion at all);
// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
// - `quick-enforce` terminates the program as fast as possible (via trapping);
// - `enforce` logs an error and then terminates the program.
//
// Notes:
// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
// to make adopting hardening easier but should not be used outside of this scenario;
// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts
// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for
// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened"
// implementation, unlike the other semantics above.
// clang-format off
# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1)
# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2)
# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3)
# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4)
// clang-format on
// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics.
// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use
// `enforce` (i.e., log and abort).
# ifndef _LIBCPP_ASSERTION_SEMANTIC
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# else
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# endif
# else
# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# error "Assertion semantics are an experimental feature."
# endif
# if defined(_LIBCPP_CXX03_LANG)
# error "Assertion semantics are not available in the C++03 mode."
# endif
# endif // _LIBCPP_ASSERTION_SEMANTIC
// } HARDENING
# define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING2(x) #x
# define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x)
@@ -320,13 +133,6 @@ _LIBCPP_HARDENING_MODE_DEBUG
// When this option is used, the token passed to `std::random_device`'s // When this option is used, the token passed to `std::random_device`'s
// constructor *must* be "/dev/urandom" -- anything else is an error. // 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 // _LIBCPP_USING_WIN32_RANDOM
// Use rand_s(), for use on Windows. // Use rand_s(), for use on Windows.
// When this option is used, the token passed to `std::random_device`'s // When this option is used, the token passed to `std::random_device`'s
@@ -338,8 +144,6 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_USING_GETENTROPY # define _LIBCPP_USING_GETENTROPY
# elif defined(__Fuchsia__) # elif defined(__Fuchsia__)
# define _LIBCPP_USING_FUCHSIA_CPRNG # define _LIBCPP_USING_FUCHSIA_CPRNG
# elif defined(__native_client__)
# define _LIBCPP_USING_NACL_RANDOM
# elif defined(_LIBCPP_WIN32API) # elif defined(_LIBCPP_WIN32API)
# define _LIBCPP_USING_WIN32_RANDOM # define _LIBCPP_USING_WIN32_RANDOM
# else # else
@@ -348,7 +152,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# ifndef _LIBCPP_CXX03_LANG # ifndef _LIBCPP_CXX03_LANG
# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp) # define _LIBCPP_ALIGNOF(...) alignof(__VA_ARGS__)
# define _ALIGNAS_TYPE(x) alignas(x) # define _ALIGNAS_TYPE(x) alignas(x)
# define _ALIGNAS(x) alignas(x) # define _ALIGNAS(x) alignas(x)
# define _NOEXCEPT noexcept # define _NOEXCEPT noexcept
@@ -357,7 +161,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# else # else
# define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp) # define _LIBCPP_ALIGNOF(...) _Alignof(__VA_ARGS__)
# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x)))) # define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x))))
# define _ALIGNAS(x) __attribute__((__aligned__(x))) # define _ALIGNAS(x) __attribute__((__aligned__(x)))
# define nullptr __nullptr # define nullptr __nullptr
@@ -471,6 +275,12 @@ typedef __char32_t char32_t;
# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) # define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str)
# endif # endif
// Macros to enter and leave a state where deprecation warnings are suppressed.
# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \
_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") \
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations")
# define _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_DIAGNOSTIC_POP
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
# define _LIBCPP_HARDENING_SIG f # define _LIBCPP_HARDENING_SIG f
# elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE # elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE
@@ -481,6 +291,16 @@ typedef __char32_t char32_t;
# define _LIBCPP_HARDENING_SIG n // "none" # define _LIBCPP_HARDENING_SIG n // "none"
# endif # endif
# if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
# define _LIBCPP_ASSERTION_SEMANTIC_SIG o
# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# define _LIBCPP_ASSERTION_SEMANTIC_SIG q
# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# define _LIBCPP_ASSERTION_SEMANTIC_SIG e
# else
# define _LIBCPP_ASSERTION_SEMANTIC_SIG i // `ignore`
# endif
# if !_LIBCPP_HAS_EXCEPTIONS # if !_LIBCPP_HAS_EXCEPTIONS
# define _LIBCPP_EXCEPTIONS_SIG n # define _LIBCPP_EXCEPTIONS_SIG n
# else # else
@@ -488,7 +308,9 @@ typedef __char32_t char32_t;
# endif # endif
# define _LIBCPP_ODR_SIGNATURE \ # define _LIBCPP_ODR_SIGNATURE \
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_EXCEPTIONS_SIG), _LIBCPP_VERSION) _LIBCPP_CONCAT( \
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_ASSERTION_SEMANTIC_SIG), _LIBCPP_EXCEPTIONS_SIG), \
_LIBCPP_VERSION)
// This macro marks a symbol as being hidden from libc++'s ABI. This is achieved // This macro marks a symbol as being hidden from libc++'s ABI. This is achieved
// on two levels: // on two levels:
@@ -550,16 +372,6 @@ typedef __char32_t char32_t;
# endif # endif
# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
# ifdef _LIBCPP_BUILDING_LIBRARY
# if _LIBCPP_ABI_VERSION > 1
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
# else
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1
# endif
# else
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
# endif
// Clang modules take a significant compile time hit when pushing and popping diagnostics. // Clang modules take a significant compile time hit when pushing and popping diagnostics.
// Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can // Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can
// simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined. // simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined.
@@ -676,27 +488,6 @@ typedef __char32_t char32_t;
# endif # endif
# endif # endif
// It is not yet possible to use aligned_alloc() on all Apple platforms since
// 10.15 was the first version to ship an implementation of aligned_alloc().
# if defined(__APPLE__)
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000)
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 0
# else
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1
# endif
# elif defined(__ANDROID__) && __ANDROID_API__ < 28
// Android only provides aligned_alloc when targeting API 28 or higher.
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 0
# else
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1
# endif
# if defined(__APPLE__) || defined(__FreeBSD__) # if defined(__APPLE__) || defined(__FreeBSD__)
# define _LIBCPP_WCTYPE_IS_MASK # define _LIBCPP_WCTYPE_IS_MASK
# endif # endif
@@ -727,6 +518,15 @@ typedef __char32_t char32_t;
# define _LIBCPP_DEPRECATED_(m) # define _LIBCPP_DEPRECATED_(m)
# endif # endif
// FIXME: using `#warning` causes diagnostics from system headers which include deprecated headers. This can only be
// enabled again once https://github.com/llvm/llvm-project/pull/168041 (or a similar feature) has landed, since that
// allows suppression in system headers.
# if defined(__DEPRECATED) && __DEPRECATED && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) && 0
# define _LIBCPP_DIAGNOSE_DEPRECATED_HEADERS 1
# else
# define _LIBCPP_DIAGNOSE_DEPRECATED_HEADERS 0
# endif
# if !defined(_LIBCPP_CXX03_LANG) # if !defined(_LIBCPP_CXX03_LANG)
# define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED # define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED
# else # else
@@ -771,17 +571,6 @@ typedef __char32_t char32_t;
# define _LIBCPP_DEPRECATED_WITH_CHAR8_T # define _LIBCPP_DEPRECATED_WITH_CHAR8_T
# endif # endif
// Macros to enter and leave a state where deprecation warnings are suppressed.
# if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC)
# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \
_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
# define _LIBCPP_SUPPRESS_DEPRECATED_POP _Pragma("GCC diagnostic pop")
# else
# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH
# define _LIBCPP_SUPPRESS_DEPRECATED_POP
# endif
# if _LIBCPP_STD_VER <= 11 # if _LIBCPP_STD_VER <= 11
# define _LIBCPP_EXPLICIT_SINCE_CXX14 # define _LIBCPP_EXPLICIT_SINCE_CXX14
# else # else
@@ -861,18 +650,10 @@ typedef __char32_t char32_t;
# endif // _LIBCPP_HAS_THREAD_API # endif // _LIBCPP_HAS_THREAD_API
# endif // _LIBCPP_HAS_THREADS # endif // _LIBCPP_HAS_THREADS
# if _LIBCPP_HAS_THREAD_API_PTHREAD # if !_LIBCPP_HAS_THREAD_API_PTHREAD
# if defined(__ANDROID__) && __ANDROID_API__ >= 30 # define _LIBCPP_HAS_COND_CLOCKWAIT 0
# define _LIBCPP_HAS_COND_CLOCKWAIT 1 # elif (defined(__ANDROID__) && __ANDROID_API__ >= 30) || _LIBCPP_GLIBC_PREREQ(2, 30)
# elif defined(_LIBCPP_GLIBC_PREREQ) # define _LIBCPP_HAS_COND_CLOCKWAIT 1
# if _LIBCPP_GLIBC_PREREQ(2, 30)
# define _LIBCPP_HAS_COND_CLOCKWAIT 1
# else
# define _LIBCPP_HAS_COND_CLOCKWAIT 0
# endif
# else
# define _LIBCPP_HAS_COND_CLOCKWAIT 0
# endif
# else # else
# define _LIBCPP_HAS_COND_CLOCKWAIT 0 # define _LIBCPP_HAS_COND_CLOCKWAIT 0
# endif # endif
@@ -951,8 +732,8 @@ typedef __char32_t char32_t;
# endif # endif
# endif # endif
# if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(__no_thread_safety_analysis__) # if __has_cpp_attribute(_Clang::__no_thread_safety_analysis__)
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((__no_thread_safety_analysis__)) # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS [[_Clang::__no_thread_safety_analysis__]]
# else # else
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
# endif # endif
@@ -1038,12 +819,8 @@ typedef __char32_t char32_t;
// the latter depends on internal GNU libc details that are not appropriate // the latter depends on internal GNU libc details that are not appropriate
// to depend on here, so any declarations present when __cpp_char8_t is not // to depend on here, so any declarations present when __cpp_char8_t is not
// defined are ignored. // defined are ignored.
# if defined(_LIBCPP_GLIBC_PREREQ) # if _LIBCPP_GLIBC_PREREQ(2, 36) && defined(__cpp_char8_t)
# if _LIBCPP_GLIBC_PREREQ(2, 36) && defined(__cpp_char8_t) # define _LIBCPP_HAS_C8RTOMB_MBRTOC8 1
# define _LIBCPP_HAS_C8RTOMB_MBRTOC8 1
# else
# define _LIBCPP_HAS_C8RTOMB_MBRTOC8 0
# endif
# else # else
# define _LIBCPP_HAS_C8RTOMB_MBRTOC8 0 # define _LIBCPP_HAS_C8RTOMB_MBRTOC8 0
# endif # endif
@@ -1067,8 +844,7 @@ typedef __char32_t char32_t;
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") # define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
# endif # endif
// TODO(LLVM 22): Remove the workaround # if defined(__OBJC__) && defined(_LIBCPP_APPLE_CLANG_VER)
# if defined(__OBJC__) && (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER < 2001)
# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS # define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS
# endif # endif
@@ -1153,12 +929,33 @@ typedef __char32_t char32_t;
# define _LIBCPP_DIAGNOSE_WARNING(...) # define _LIBCPP_DIAGNOSE_WARNING(...)
# endif # endif
# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_APPLE_CLANG_VER) && \
(!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2001)
# define _LIBCPP_DIAGNOSE_IF(...) __attribute__((__diagnose_if__(__VA_ARGS__)))
# else
# define _LIBCPP_DIAGNOSE_IF(...)
# endif
# define _LIBCPP_DIAGNOSE_NULLPTR_IF(condition, condition_description) \
_LIBCPP_DIAGNOSE_IF( \
condition, \
"null passed to callee that requires a non-null argument" condition_description, \
"warning", \
"nonnull")
# if __has_cpp_attribute(_Clang::__lifetimebound__) # if __has_cpp_attribute(_Clang::__lifetimebound__)
# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] # define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]]
# else # else
# define _LIBCPP_LIFETIMEBOUND # define _LIBCPP_LIFETIMEBOUND
# endif # endif
// This is to work around https://llvm.org/PR156809
# ifndef _LIBCPP_CXX03_LANG
# define _LIBCPP_CTOR_LIFETIMEBOUND _LIBCPP_LIFETIMEBOUND
# else
# define _LIBCPP_CTOR_LIFETIMEBOUND
# endif
# if __has_cpp_attribute(_Clang::__noescape__) # if __has_cpp_attribute(_Clang::__noescape__)
# define _LIBCPP_NOESCAPE [[_Clang::__noescape__]] # define _LIBCPP_NOESCAPE [[_Clang::__noescape__]]
# else # else
@@ -1172,12 +969,6 @@ typedef __char32_t char32_t;
# define _LIBCPP_NO_SPECIALIZATIONS # define _LIBCPP_NO_SPECIALIZATIONS
# endif # endif
# if __has_cpp_attribute(_Clang::__standalone_debug__)
# define _LIBCPP_STANDALONE_DEBUG [[_Clang::__standalone_debug__]]
# else
# define _LIBCPP_STANDALONE_DEBUG
# endif
# if __has_cpp_attribute(_Clang::__preferred_name__) # if __has_cpp_attribute(_Clang::__preferred_name__)
# define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]] # define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]]
# else # else
@@ -1257,14 +1048,6 @@ typedef __char32_t char32_t;
# define _LIBCPP_DIAGNOSE_NULLPTR # define _LIBCPP_DIAGNOSE_NULLPTR
# endif # endif
// TODO(LLVM 22): Remove this macro once LLVM19 support ends. __cpp_explicit_this_parameter has been set in LLVM20.
// Clang-18 has support for deducing this, but it does not set the FTM.
# if defined(__cpp_explicit_this_parameter) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1800)
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 1
# else
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 0
# endif
#endif // __cplusplus #endif // __cplusplus
#endif // _LIBCPP___CONFIG #endif // _LIBCPP___CONFIG
+14 -24
View File
@@ -61,19 +61,9 @@
// According to the Standard, `bitset::operator[] const` returns bool // According to the Standard, `bitset::operator[] const` returns bool
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL # define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
// In LLVM 20, we've changed to take these ABI breaks unconditionally. These flags only exist in case someone is running
// into the static_asserts we added to catch the ABI break and don't care that it is one.
// TODO(LLVM 22): Remove these flags
# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
// These flags are documented in ABIGuarantees.rst // These flags are documented in ABIGuarantees.rst
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT # define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON # define _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI # define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI # define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION # define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
@@ -84,25 +74,16 @@
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE # define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
# define _LIBCPP_ABI_NO_ITERATOR_BASES # define _LIBCPP_ABI_NO_ITERATOR_BASES
# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT # define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT
# define _LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION # define _LIBCPP_ABI_OPTIMIZED_FUNCTION
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO # define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION # define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY # define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW # define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION # define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
# define _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
#elif _LIBCPP_ABI_VERSION == 1 #elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
// applications compiled against older libraries. This is unnecessary with
// COFF dllexport semantics, since dllexport forces a non-inline definition
// of inline functions to be emitted anyway. Our own non-inline copy would
// conflict with the dllexport-emitted copy, so we disable it. For XCOFF,
// the linker will take issue with the symbols in the shared object if the
// weak inline methods get visibility (such as from -fvisibility-inlines-hidden),
// so disable it.
# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
# endif
// Feature macros for disabling pre ABI v1 features. All of these options // Feature macros for disabling pre ABI v1 features. All of these options
// are deprecated. // are deprecated.
# if defined(__FreeBSD__) # if defined(__FreeBSD__)
@@ -110,11 +91,20 @@
# endif # endif
#endif #endif
// TODO(LLVM 22): Remove this check
#if defined(_LIBCPP_ABI_NO_ITERATOR_BASES) && !defined(_LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER)
# ifndef _LIBCPP_ONLY_NO_ITERATOR_BASES
# error "You probably want to define _LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER. This has been split out from" \
" _LIBCPP_ABI_NO_ITERATOR_BASES to allow only removing the second iterator member, since they aren't really related." \
"If you actually want this ABI configuration, please define _LIBCPP_ONLY_NO_ITERATOR_BASES instead."
# endif
#endif
// We had some bugs where we use [[no_unique_address]] together with construct_at, // We had some bugs where we use [[no_unique_address]] together with construct_at,
// which causes UB as the call on construct_at could write to overlapping subobjects // which causes UB as the call on construct_at could write to overlapping subobjects
// //
// https://github.com/llvm/llvm-project/issues/70506 // https://llvm.org/PR70506
// https://github.com/llvm/llvm-project/issues/70494 // https://llvm.org/PR70494
// //
// To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions. // To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions.
// The macro below is used for all classes whose ABI have changed as part of fixing these bugs. // The macro below is used for all classes whose ABI have changed as part of fixing these bugs.
+65 -118
View File
@@ -17,62 +17,17 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
// Libc++ is shipped by various vendors. In particular, it is used as a system // This file defines a framework that can be used by vendors to encode the version of an operating system that various
// library on macOS, iOS and other Apple platforms. In order for users to be // features of libc++ has been shipped in. This is primarily intended to allow safely deploying an executable built with
// able to compile a binary that is intended to be deployed to an older version // a new version of the library on a platform containing an older version of the built library.
// of a platform, Clang provides availability attributes [1]. These attributes // Detailed documentation for this can be found at https://libcxx.llvm.org/VendorDocumentation.html#availability-markup
// can be placed on declarations and are used to describe the life cycle of a
// symbol in the library.
//
// The main goal is to ensure a compile-time error if a symbol that hasn't been
// introduced in a previously released library is used in a program that targets
// that previously released library. Normally, this would be a load-time error
// when one tries to launch the program against the older library.
//
// For example, the filesystem library was introduced in the dylib in LLVM 9.
// On Apple platforms, this corresponds to macOS 10.15. If a user compiles on
// a macOS 10.15 host but targets macOS 10.13 with their program, the compiler
// would normally not complain (because the required declarations are in the
// headers), but the dynamic loader would fail to find the symbols when actually
// trying to launch the program on macOS 10.13. To turn this into a compile-time
// issue instead, declarations are annotated with when they were introduced, and
// the compiler can produce a diagnostic if the program references something that
// isn't available on the deployment target.
//
// This mechanism is general in nature, and any vendor can add their markup to
// the library (see below). Whenever a new feature is added that requires support
// in the shared library, two macros are added below to allow marking the feature
// as unavailable:
// 1. A macro named `_LIBCPP_AVAILABILITY_HAS_<feature>` which must be defined
// to `_LIBCPP_INTRODUCED_IN_<version>` for the appropriate LLVM version.
// 2. A macro named `_LIBCPP_AVAILABILITY_<feature>`, which must be defined to
// `_LIBCPP_INTRODUCED_IN_<version>_MARKUP` for the appropriate LLVM version.
//
// When vendors decide to ship the feature as part of their shared library, they
// can update the `_LIBCPP_INTRODUCED_IN_<version>` macro (and the markup counterpart)
// based on the platform version they shipped that version of LLVM in. The library
// will then use this markup to provide an optimal user experience on these platforms.
//
// Furthermore, many features in the standard library have corresponding
// feature-test macros. The `_LIBCPP_AVAILABILITY_HAS_<feature>` macros
// are checked by the corresponding feature-test macros generated by
// generate_feature_test_macro_components.py to ensure that the library
// doesn't announce a feature as being implemented if it is unavailable on
// the deployment target.
//
// Note that this mechanism is disabled by default in the "upstream" libc++.
// Availability annotations are only meaningful when shipping libc++ inside
// a platform (i.e. as a system library), and so vendors that want them should
// turn those annotations on at CMake configuration time.
//
// [1]: https://clang.llvm.org/docs/AttributeReference.html#availability
// Availability markup is disabled when building the library, or when a non-Clang // Availability markup is disabled when building the library, or when a non-Clang
// compiler is used because only Clang supports the necessary attributes. // compiler is used because only Clang supports the necessary attributes.
// //
// We also allow users to force-disable availability markup via the `_LIBCPP_DISABLE_AVAILABILITY` // We also allow users to force-disable availability markup via the `_LIBCPP_DISABLE_AVAILABILITY`
// macro because that is the only way to work around a Clang bug related to availability // macro because that is the only way to work around a Clang bug related to availability
// attributes: https://github.com/llvm/llvm-project/issues/134151. // attributes: https://llvm.org/PR134151.
// Once that bug has been fixed, we should remove the macro. // Once that bug has been fixed, we should remove the macro.
#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || \ #if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || \
!defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_DISABLE_AVAILABILITY) !defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_DISABLE_AVAILABILITY)
@@ -84,6 +39,9 @@
// in all versions of the library are available. // in all versions of the library are available.
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
# define _LIBCPP_INTRODUCED_IN_LLVM_22 1
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
# define _LIBCPP_INTRODUCED_IN_LLVM_21 1 # define _LIBCPP_INTRODUCED_IN_LLVM_21 1
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */ # define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
@@ -108,32 +66,55 @@
# define _LIBCPP_INTRODUCED_IN_LLVM_12 1 # define _LIBCPP_INTRODUCED_IN_LLVM_12 1
# define _LIBCPP_INTRODUCED_IN_LLVM_12_ATTRIBUTE /* nothing */ # define _LIBCPP_INTRODUCED_IN_LLVM_12_ATTRIBUTE /* nothing */
# define _LIBCPP_INTRODUCED_IN_LLVM_11 1
# define _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE /* nothing */
# define _LIBCPP_INTRODUCED_IN_LLVM_9 1
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE /* nothing */
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH /* nothing */
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP /* nothing */
#elif defined(__APPLE__) #elif defined(__APPLE__)
// clang-format off // clang-format off
// LLVM 22
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_22 0
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))
// LLVM 21 // LLVM 21
// TODO: Fill this in // TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0 # define _LIBCPP_INTRODUCED_IN_LLVM_21 0
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE __attribute__((unavailable)) # define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE __attribute__((unavailable))
// LLVM 20 // LLVM 20
// TODO: Fill this in //
# define _LIBCPP_INTRODUCED_IN_LLVM_20 0 // Note that versions for most Apple OSes were bumped forward and aligned in that release.
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE __attribute__((unavailable)) # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 260000) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 260000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 260000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 260000) || \
(defined(__ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__ < 100000)
# define _LIBCPP_INTRODUCED_IN_LLVM_20 0
# else
# define _LIBCPP_INTRODUCED_IN_LLVM_20 1
# endif
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE \
__attribute__((availability(macos, strict, introduced = 26.0))) \
__attribute__((availability(ios, strict, introduced = 26.0))) \
__attribute__((availability(tvos, strict, introduced = 26.0))) \
__attribute__((availability(watchos, strict, introduced = 26.0))) \
__attribute__((availability(bridgeos, strict, introduced = 10.0)))
// LLVM 19 // LLVM 19
// TODO: Fill this in # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 150400) || \
# define _LIBCPP_INTRODUCED_IN_LLVM_19 0 (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 180400) || \
# define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE __attribute__((unavailable)) (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 180400) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 110400) || \
(defined(__ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__ < 90400)
# define _LIBCPP_INTRODUCED_IN_LLVM_19 0
# else
# define _LIBCPP_INTRODUCED_IN_LLVM_19 1
# endif
# define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE \
__attribute__((availability(macos, strict, introduced = 15.4))) \
__attribute__((availability(ios, strict, introduced = 18.4))) \
__attribute__((availability(tvos, strict, introduced = 18.4))) \
__attribute__((availability(watchos, strict, introduced = 11.4))) \
__attribute__((availability(bridgeos, strict, introduced = 9.4)))
// LLVM 18 // LLVM 18
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 150000) || \ # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 150000) || \
@@ -215,47 +196,13 @@
__attribute__((availability(bridgeos, strict, introduced = 6.0))) \ __attribute__((availability(bridgeos, strict, introduced = 6.0))) \
__attribute__((availability(driverkit, strict, introduced = 21.3))) __attribute__((availability(driverkit, strict, introduced = 21.3)))
// LLVM 11 # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 150000) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 150000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 80000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) (defined(__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__ < 200000)
# define _LIBCPP_INTRODUCED_IN_LLVM_11 0 # warning "The selected platform is no longer supported by libc++."
# else
# define _LIBCPP_INTRODUCED_IN_LLVM_11 1
# endif # endif
# define _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE \
__attribute__((availability(macos, strict, introduced = 11.0))) \
__attribute__((availability(ios, strict, introduced = 14.0))) \
__attribute__((availability(tvos, strict, introduced = 14.0))) \
__attribute__((availability(watchos, strict, introduced = 7.0)))
// LLVM 9
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000)
# define _LIBCPP_INTRODUCED_IN_LLVM_9 0
# else
# define _LIBCPP_INTRODUCED_IN_LLVM_9 1
# endif
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE \
__attribute__((availability(macos, strict, introduced = 10.15))) \
__attribute__((availability(ios, strict, introduced = 13.0))) \
__attribute__((availability(tvos, strict, introduced = 13.0))) \
__attribute__((availability(watchos, strict, introduced = 6.0)))
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH \
_Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \
_Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \
_Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \
_Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))")
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP \
_Pragma("clang attribute pop") \
_Pragma("clang attribute pop") \
_Pragma("clang attribute pop") \
_Pragma("clang attribute pop")
// clang-format on
#else #else
@@ -266,19 +213,12 @@
#endif #endif
// These macros control the availability of all parts of <filesystem> that // This controls the availability of new implementation of std::atomic's
// depend on something in the dylib. // wait, notify_one and notify_all. The new implementation uses
#define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9 // the native atomic wait/notify operations on platforms that support them
#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE // based on the size of the atomic type, instead of the type itself.
#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH #define _LIBCPP_AVAILABILITY_HAS_NEW_SYNC _LIBCPP_INTRODUCED_IN_LLVM_22
#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP #define _LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE
// This controls the availability of the C++20 synchronization library,
// which requires shared library support for various operations
// (see libcxx/src/atomic.cpp). This includes <barier>, <latch>,
// <semaphore>, and notification functions on std::atomic.
#define _LIBCPP_AVAILABILITY_HAS_SYNC _LIBCPP_INTRODUCED_IN_LLVM_11
#define _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE
// Enable additional explicit instantiations of iostreams components. This // Enable additional explicit instantiations of iostreams components. This
// reduces the number of weak definitions generated in programs that use // reduces the number of weak definitions generated in programs that use
@@ -307,7 +247,7 @@
// This controls the availability of the C++17 std::pmr library, // This controls the availability of the C++17 std::pmr library,
// which is implemented in large part in the built library. // which is implemented in large part in the built library.
// //
// TODO: Enable std::pmr markup once https://github.com/llvm/llvm-project/issues/40340 has been fixed // TODO: Enable std::pmr markup once https://llvm.org/PR40340 has been fixed
// Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support // Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support
// it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we // it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we
// use availability annotations until that bug has been fixed. // use availability annotations until that bug has been fixed.
@@ -364,4 +304,11 @@
# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION # define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION
#endif #endif
// Only define a bunch of symbols in the dylib if we need to be compatible with LLVM 7 headers or older
# if defined(_LIBCPP_BUILDING_LIBRARY) && _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 8
# define _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8
# else
# define _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 _LIBCPP_HIDE_FROM_ABI
# endif
#endif // _LIBCPP___CONFIGURATION_AVAILABILITY_H #endif // _LIBCPP___CONFIGURATION_AVAILABILITY_H
+6 -6
View File
@@ -33,16 +33,16 @@
// Warn if a compiler version is used that is not supported anymore // Warn if a compiler version is used that is not supported anymore
// LLVM RELEASE Update the minimum compiler versions // LLVM RELEASE Update the minimum compiler versions
# if defined(_LIBCPP_CLANG_VER) # if defined(_LIBCPP_CLANG_VER)
# if _LIBCPP_CLANG_VER < 1900 # if _LIBCPP_CLANG_VER < 2001
# warning "Libc++ only supports Clang 19 and later" # warning "Libc++ only supports Clang 20 and later"
# endif # endif
# elif defined(_LIBCPP_APPLE_CLANG_VER) # elif defined(_LIBCPP_APPLE_CLANG_VER)
# if _LIBCPP_APPLE_CLANG_VER < 1500 # if _LIBCPP_APPLE_CLANG_VER < 1700
# warning "Libc++ only supports AppleClang 15 and later" # warning "Libc++ only supports AppleClang 26 and later"
# endif # endif
# elif defined(_LIBCPP_GCC_VER) # elif defined(_LIBCPP_GCC_VER)
# if _LIBCPP_GCC_VER < 1400 # if _LIBCPP_GCC_VER < 1500
# warning "Libc++ only supports GCC 14 and later" # warning "Libc++ only supports GCC 15 and later"
# endif # endif
# endif # endif
+38
View File
@@ -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___CONFIGURATION_EXPERIMENTAL_H
#define _LIBCPP___CONFIGURATION_EXPERIMENTAL_H
/* zig patch: instead of including __config_site, zig adds -D flags when compiling */
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
# pragma GCC system_header
#endif
#if __has_feature(experimental_library)
# ifndef _LIBCPP_ENABLE_EXPERIMENTAL
# define _LIBCPP_ENABLE_EXPERIMENTAL
# endif
#endif
// Incomplete features get their own specific disabling flags. This makes it
// easier to grep for target specific flags once the feature is complete.
#if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY)
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1
#else
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0
#endif
#define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
#define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
#define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
#define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
#define _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
#endif // _LIBCPP___CONFIGURATION_EXPERIMENTAL_H
+215
View File
@@ -0,0 +1,215 @@
//===----------------------------------------------------------------------===//
//
// 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___CONFIGURATION_HARDENING_H
#define _LIBCPP___CONFIGURATION_HARDENING_H
/* zig patch: instead of including __config_site, zig adds -D flags when compiling */
#include <__configuration/experimental.h>
#include <__configuration/language.h>
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
# pragma GCC system_header
#endif
// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated.
// Since hardening went through several changes (many of which impacted user-facing macros),
// we're keeping these checks around for a bit longer than usual. Failure to properly configure
// hardening results in checks being dropped silently, which is a pretty big deal.
#if defined(_LIBCPP_ENABLE_ASSERTIONS)
# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
#endif
#if defined(_LIBCPP_ENABLE_HARDENED_MODE)
# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
#endif
#if defined(_LIBCPP_ENABLE_SAFE_MODE)
# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
#endif
#if defined(_LIBCPP_ENABLE_DEBUG_MODE)
# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
#endif
// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values:
//
// - `_LIBCPP_HARDENING_MODE_NONE`;
// - `_LIBCPP_HARDENING_MODE_FAST`;
// - `_LIBCPP_HARDENING_MODE_EXTENSIVE`;
// - `_LIBCPP_HARDENING_MODE_DEBUG`.
//
// These values have the following effects:
//
// - `_LIBCPP_HARDENING_MODE_NONE` -- sets the hardening mode to "none" which disables all runtime hardening checks;
//
// - `_LIBCPP_HARDENING_MODE_FAST` -- sets that hardening mode to "fast". The fast mode enables security-critical checks
// that can be done with relatively little runtime overhead in constant time;
//
// - `_LIBCPP_HARDENING_MODE_EXTENSIVE` -- sets the hardening mode to "extensive". The extensive mode is a superset of
// the fast mode that additionally enables checks that are relatively cheap and prevent common types of logic errors
// but are not necessarily security-critical;
//
// - `_LIBCPP_HARDENING_MODE_DEBUG` -- sets the hardening mode to "debug". The debug mode is a superset of the extensive
// mode and enables all checks available in the library, including internal assertions. Checks that are part of the
// debug mode can be very expensive and thus the debug mode is intended to be used for testing, not in production.
// Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These
// macros are only for internal use -- users should only pick one of the high-level hardening modes described above.
//
// - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and
// a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid:
// - the sentinel is reachable from the begin iterator;
// - TODO(hardening): both iterators refer to the same container.
//
// - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through
// the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access
// a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like
// `optional` and `function` are considered one-element containers for the purposes of this check.
//
// - `_LIBCPP_ASSERT_NON_NULL` -- checks that the pointer being dereferenced is not null. On most modern platforms zero
// address does not refer to an actual location in memory, so a null pointer dereference would not compromize the
// memory security of a program (however, it is still undefined behavior that can result in strange errors due to
// compiler optimizations).
//
// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the
// given ranges do not overlap.
//
// - `_LIBCPP_ASSERT_VALID_DEALLOCATION` -- checks that an attempt to deallocate memory is valid (e.g. the given object
// was allocated by the given allocator). Violating this category typically results in a memory leak.
//
// - `_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL` -- checks that a call to an external API doesn't fail in
// an unexpected manner. This includes triggering documented cases of undefined behavior in an external library (like
// attempting to unlock an unlocked mutex in pthreads). Any API external to the library falls under this category
// (from system calls to compiler intrinsics). We generally don't expect these failures to compromize memory safety or
// otherwise create an immediate security issue.
//
// - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure
// the containers have compatible allocators.
//
// - `_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN` -- checks that the given argument is within the domain of valid arguments
// for the function. Violating this typically produces an incorrect result (e.g. the clamp algorithm returns the
// original value without clamping it due to incorrect functors) or puts an object into an invalid state (e.g.
// a string view where only a subset of elements is possible to access). This category is for assertions violating
// which doesn't cause any immediate issues in the library -- whatever the consequences are, they will happen in the
// user code.
//
// - `_LIBCPP_ASSERT_PEDANTIC` -- checks prerequisites which are imposed by the Standard, but violating which happens to
// be benign in our implementation.
//
// - `_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT` -- checks that the given argument satisfies the semantic requirements imposed
// by the Standard. Typically, there is no simple way to completely prove that a semantic requirement is satisfied;
// thus, this would often be a heuristic check and it might be quite expensive.
//
// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on
// user input.
//
// - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet.
// clang-format off
# define _LIBCPP_HARDENING_MODE_NONE (1 << 1)
# define _LIBCPP_HARDENING_MODE_FAST (1 << 2)
# define _LIBCPP_HARDENING_MODE_EXTENSIVE (1 << 4) // Deliberately not ordered.
# define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3)
// clang-format on
#ifndef _LIBCPP_HARDENING_MODE
# ifndef _LIBCPP_HARDENING_MODE_DEFAULT
# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \
`__config_site` header, please make sure your installation of libc++ is not broken.
# endif
# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT
#endif
#if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \
_LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \
_LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
# error _LIBCPP_HARDENING_MODE must be set to one of the following values: \
_LIBCPP_HARDENING_MODE_NONE, \
_LIBCPP_HARDENING_MODE_FAST, \
_LIBCPP_HARDENING_MODE_EXTENSIVE, \
_LIBCPP_HARDENING_MODE_DEBUG
#endif
// The library provides the macro `_LIBCPP_ASSERTION_SEMANTIC` for configuring the assertion semantic used by hardening;
// it can be set to one of the following values:
//
// - `_LIBCPP_ASSERTION_SEMANTIC_IGNORE`;
// - `_LIBCPP_ASSERTION_SEMANTIC_OBSERVE`;
// - `_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE`;
// - `_LIBCPP_ASSERTION_SEMANTIC_ENFORCE`.
//
// libc++ assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts
// `ignore` semantic which wouldn't evaluate the assertion at all);
// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
// - `quick-enforce` terminates the program as fast as possible (via trapping);
// - `enforce` logs an error and then terminates the program.
//
// Additionally, a special `hardening-dependent` value selects the assertion semantic based on the hardening mode in
// effect: the production-capable modes (`fast` and `extensive`) map to `quick_enforce` and the `debug` mode maps to
// `enforce`. The `hardening-dependent` semantic cannot be selected explicitly, it is only used when no assertion
// semantic is provided by the user _and_ the library's default semantic is configured to be dependent on hardening.
//
// Notes:
// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
// to make adopting hardening easier but should not be used outside of this scenario;
// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts
// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for
// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened"
// implementation, unlike the other semantics above.
// clang-format off
# define _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT (1 << 1)
# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 2)
# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 3)
# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 4)
# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 5)
// clang-format on
// If the user attempts to configure the assertion semantic, check that it is allowed in the current environment.
#if defined(_LIBCPP_ASSERTION_SEMANTIC)
# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# error "Assertion semantics are an experimental feature."
# endif
# if defined(_LIBCPP_CXX03_LANG)
# error "Assertion semantics are not available in the C++03 mode."
# endif
#endif // defined(_LIBCPP_ASSERTION_SEMANTIC)
// User-provided semantic takes top priority -- don't override if set.
#ifndef _LIBCPP_ASSERTION_SEMANTIC
# ifndef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
# error _LIBCPP_ASSERTION_SEMANTIC_DEFAULT is not defined. This definition should be set at configuration time in \
the `__config_site` header, please make sure your installation of libc++ is not broken.
# endif
# if _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_DEFAULT
# else
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# else
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
# endif
# endif // _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT
#endif // #ifndef _LIBCPP_ASSERTION_SEMANTIC
// Finally, validate the selected semantic (in case the user tries setting it to an incorrect value):
#if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_IGNORE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE && \
_LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \
_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \
_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \
_LIBCPP_ASSERTION_SEMANTIC_ENFORCE
#endif
#endif // _LIBCPP___CONFIGURATION_HARDENING_H
+3
View File
@@ -18,6 +18,9 @@
// NOLINTBEGIN(libcpp-cpp-version-check) // NOLINTBEGIN(libcpp-cpp-version-check)
#ifdef __cplusplus #ifdef __cplusplus
# if __cplusplus < 201103L
# define _LIBCPP_CXX03_LANG
# endif
# if __cplusplus <= 201103L # if __cplusplus <= 201103L
# define _LIBCPP_STD_VER 11 # define _LIBCPP_STD_VER 11
# elif __cplusplus <= 201402L # elif __cplusplus <= 201402L
+9 -16
View File
@@ -31,22 +31,15 @@
#endif #endif
// Need to detect which libc we're using if we're on Linux. // Need to detect which libc we're using if we're on Linux.
#if defined(__linux__) || defined(__AMDGPU__) || defined(__NVPTX__) #if (defined(__linux__) || defined(__AMDGPU__) || defined(__NVPTX__)) && __has_include(<features.h>)
# if __has_include(<features.h>) # include <features.h>
# include <features.h> # if defined(__GLIBC_PREREQ)
# if defined(__GLIBC_PREREQ) # define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b) # else
# else # define _LIBCPP_GLIBC_PREREQ(a, b) 0
# define _LIBCPP_GLIBC_PREREQ(a, b) 0 # endif // defined(__GLIBC_PREREQ)
# endif // defined(__GLIBC_PREREQ) #else
# endif # define _LIBCPP_GLIBC_PREREQ(a, b) 0
#endif
// This is required in order for _NEWLIB_VERSION to be defined in places where we use it.
// TODO: We shouldn't be including arbitrarily-named headers from libc++ since this can break valid
// user code. Move code paths that need _NEWLIB_VERSION to another customization mechanism.
#if __has_include(<picolibc.h>)
# include <picolibc.h>
#endif #endif
#ifndef __BYTE_ORDER__ #ifndef __BYTE_ORDER__
+9 -9
View File
@@ -44,9 +44,9 @@ public:
} }
// [coroutine.handle.export.import], export/import // [coroutine.handle.export.import], export/import
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
_LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
coroutine_handle __tmp; coroutine_handle __tmp;
__tmp.__handle_ = __addr; __tmp.__handle_ = __addr;
return __tmp; return __tmp;
@@ -55,7 +55,7 @@ public:
// [coroutine.handle.observers], observers // [coroutine.handle.observers], observers
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; } _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
_LIBCPP_HIDE_FROM_ABI bool done() const { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool done() const {
_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines"); _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
return __builtin_coro_done(__handle_); return __builtin_coro_done(__handle_);
} }
@@ -100,7 +100,7 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {} _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {}
_LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) {
using _RawPromise = __remove_cv_t<_Promise>; using _RawPromise = __remove_cv_t<_Promise>;
coroutine_handle __tmp; coroutine_handle __tmp;
__tmp.__handle_ = __tmp.__handle_ =
@@ -114,9 +114,9 @@ public:
} }
// [coroutine.handle.export.import], export/import // [coroutine.handle.export.import], export/import
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
_LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
coroutine_handle __tmp; coroutine_handle __tmp;
__tmp.__handle_ = __addr; __tmp.__handle_ = __addr;
return __tmp; return __tmp;
@@ -130,7 +130,7 @@ public:
// [coroutine.handle.observers], observers // [coroutine.handle.observers], observers
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; } _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
_LIBCPP_HIDE_FROM_ABI bool done() const { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool done() const {
_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines"); _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
return __builtin_coro_done(__handle_); return __builtin_coro_done(__handle_);
} }
@@ -150,7 +150,7 @@ public:
} }
// [coroutine.handle.promise], promise access // [coroutine.handle.promise], promise access
_LIBCPP_HIDE_FROM_ABI _Promise& promise() const { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Promise& promise() const {
return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false)); return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
} }
@@ -165,7 +165,7 @@ private:
// [coroutine.handle.hash] // [coroutine.handle.hash]
template <class _Tp> template <class _Tp>
struct hash<coroutine_handle<_Tp>> { struct hash<coroutine_handle<_Tp>> {
_LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept {
return hash<void*>()(__v.address()); return hash<void*>()(__v.address());
} }
}; };
+11 -13
View File
@@ -20,8 +20,6 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
# if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)
// [coroutine.noop] // [coroutine.noop]
// [coroutine.promise.noop] // [coroutine.promise.noop]
struct noop_coroutine_promise {}; struct noop_coroutine_promise {};
@@ -37,7 +35,7 @@ public:
// [coroutine.handle.noop.observers], observers // [coroutine.handle.noop.observers], observers
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return true; } _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return true; }
_LIBCPP_HIDE_FROM_ABI constexpr bool done() const noexcept { return false; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool done() const noexcept { return false; }
// [coroutine.handle.noop.resumption], resumption // [coroutine.handle.noop.resumption], resumption
_LIBCPP_HIDE_FROM_ABI constexpr void operator()() const noexcept {} _LIBCPP_HIDE_FROM_ABI constexpr void operator()() const noexcept {}
@@ -45,23 +43,23 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr void destroy() const noexcept {} _LIBCPP_HIDE_FROM_ABI constexpr void destroy() const noexcept {}
// [coroutine.handle.noop.promise], promise access // [coroutine.handle.noop.promise], promise access
_LIBCPP_HIDE_FROM_ABI noop_coroutine_promise& promise() const noexcept { [[nodiscard]] _LIBCPP_HIDE_FROM_ABI noop_coroutine_promise& promise() const noexcept {
return *static_cast<noop_coroutine_promise*>( return *static_cast<noop_coroutine_promise*>(
__builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false)); __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false));
} }
// [coroutine.handle.noop.address], address // [coroutine.handle.noop.address], address
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
private: private:
_LIBCPP_HIDE_FROM_ABI friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept; _LIBCPP_HIDE_FROM_ABI friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
# if __has_builtin(__builtin_coro_noop) # if __has_builtin(__builtin_coro_noop)
_LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { this->__handle_ = __builtin_coro_noop(); } _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { this->__handle_ = __builtin_coro_noop(); }
void* __handle_ = nullptr; void* __handle_ = nullptr;
# elif defined(_LIBCPP_COMPILER_GCC) # elif defined(_LIBCPP_COMPILER_GCC)
// GCC doesn't implement __builtin_coro_noop(). // GCC doesn't implement __builtin_coro_noop().
// Construct the coroutine frame manually instead. // Construct the coroutine frame manually instead.
struct __noop_coroutine_frame_ty_ { struct __noop_coroutine_frame_ty_ {
@@ -78,19 +76,19 @@ private:
_LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default; _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default;
# endif // __has_builtin(__builtin_coro_noop) # endif // __has_builtin(__builtin_coro_noop)
}; };
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
# if defined(_LIBCPP_COMPILER_GCC) # if defined(_LIBCPP_COMPILER_GCC)
inline noop_coroutine_handle::__noop_coroutine_frame_ty_ noop_coroutine_handle::__noop_coroutine_frame_{}; inline noop_coroutine_handle::__noop_coroutine_frame_ty_ noop_coroutine_handle::__noop_coroutine_frame_{};
# endif # endif
// [coroutine.noop.coroutine] // [coroutine.noop.coroutine]
inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); } [[nodiscard]] 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 _LIBCPP_END_NAMESPACE_STD
@@ -27,7 +27,7 @@ template <class _RandomAccessIterator, class _Comp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { __check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
using __diff_t = __iter_diff_t<_RandomAccessIterator>; using __diff_t = __iterator_difference_type<_RandomAccessIterator>;
using _Comp_ref = __comp_ref_type<_Comp>; using _Comp_ref = __comp_ref_type<_Comp>;
if (!__libcpp_is_constant_evaluated()) { if (!__libcpp_is_constant_evaluated()) {
// Check if the range is actually sorted. // Check if the range is actually sorted.
+6 -4
View File
@@ -48,13 +48,15 @@ public:
__data_._DoFree = true; __data_._DoFree = true;
} }
exception(exception const&) _NOEXCEPT {} exception(exception const&) _NOEXCEPT : __data_() {}
exception& operator=(exception const&) _NOEXCEPT { return *this; } exception& operator=(exception const&) _NOEXCEPT { return *this; }
virtual ~exception() _NOEXCEPT {} virtual ~exception() _NOEXCEPT {}
virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } [[__nodiscard__]] virtual char const* what() const _NOEXCEPT {
return __data_._What ? __data_._What : "Unknown exception";
}
private: private:
__std_exception_data __data_; __std_exception_data __data_;
@@ -76,7 +78,7 @@ public:
_LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default;
virtual ~exception() _NOEXCEPT; virtual ~exception() _NOEXCEPT;
virtual const char* what() const _NOEXCEPT; [[__nodiscard__]] virtual const char* what() const _NOEXCEPT;
}; };
class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception { class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
@@ -85,7 +87,7 @@ public:
_LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default;
~bad_exception() _NOEXCEPT override; ~bad_exception() _NOEXCEPT override;
const char* what() const _NOEXCEPT override; [[__nodiscard__]] const char* what() const _NOEXCEPT override;
}; };
#endif // !_LIBCPP_ABI_VCRUNTIME #endif // !_LIBCPP_ABI_VCRUNTIME
+27 -5
View File
@@ -11,18 +11,24 @@
#include <__config> #include <__config>
#include <__cstddef/nullptr_t.h> #include <__cstddef/nullptr_t.h>
#include <__cstddef/size_t.h>
#include <__exception/operations.h> #include <__exception/operations.h>
#include <__memory/addressof.h> #include <__memory/addressof.h>
#include <__memory/construct_at.h> #include <__memory/construct_at.h>
#include <__type_traits/decay.h> #include <__type_traits/decay.h>
#include <__type_traits/is_pointer.h> #include <__type_traits/is_pointer.h>
#include <cstdlib> #include <__utility/move.h>
#include <__utility/swap.h>
#include <__verbose_abort>
#include <typeinfo> #include <typeinfo>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#ifndef _LIBCPP_ABI_MICROSOFT #ifndef _LIBCPP_ABI_MICROSOFT
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
@@ -30,7 +36,7 @@
namespace __cxxabiv1 { namespace __cxxabiv1 {
extern "C" { extern "C" {
_LIBCPP_OVERRIDABLE_FUNC_VIS void* __cxa_allocate_exception(size_t) throw(); _LIBCPP_OVERRIDABLE_FUNC_VIS void* __cxa_allocate_exception(std::size_t) throw();
_LIBCPP_OVERRIDABLE_FUNC_VIS void __cxa_free_exception(void*) throw(); _LIBCPP_OVERRIDABLE_FUNC_VIS void __cxa_free_exception(void*) throw();
struct __cxa_exception; struct __cxa_exception;
@@ -57,6 +63,8 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
#ifndef _LIBCPP_ABI_MICROSOFT #ifndef _LIBCPP_ABI_MICROSOFT
inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT;
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
void* __ptr_; void* __ptr_;
@@ -67,15 +75,21 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
public: public:
// exception_ptr is basically a COW string so it is trivially relocatable. // exception_ptr is basically a COW string so it is trivially relocatable.
// It is also replaceable because assignment has normal value semantics.
using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr; using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr;
using __replaceable _LIBCPP_NODEBUG = exception_ptr;
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
exception_ptr(const exception_ptr&) _NOEXCEPT; exception_ptr(const exception_ptr&) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI exception_ptr(exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) {
__other.__ptr_ = nullptr;
}
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI exception_ptr& operator=(exception_ptr&& __other) _NOEXCEPT {
exception_ptr __tmp(std::move(__other));
std::swap(__tmp, *this);
return *this;
}
~exception_ptr() _NOEXCEPT; ~exception_ptr() _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; }
@@ -88,10 +102,16 @@ public:
return !(__x == __y); return !(__x == __y);
} }
friend _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT;
friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
}; };
inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT {
std::swap(__x.__ptr_, __y.__ptr_);
}
# if _LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_HAS_EXCEPTIONS
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
template <class _Ep> template <class _Ep>
@@ -153,7 +173,7 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
# else // !_LIBCPP_HAS_EXCEPTIONS # else // !_LIBCPP_HAS_EXCEPTIONS
template <class _Ep> template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT { _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT {
std::abort(); _LIBCPP_VERBOSE_ABORT("make_exception_ptr was called in -fno-exceptions mode");
} }
# endif // _LIBCPP_HAS_EXCEPTIONS # endif // _LIBCPP_HAS_EXCEPTIONS
@@ -201,4 +221,6 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
#endif // _LIBCPP_ABI_MICROSOFT #endif // _LIBCPP_ABI_MICROSOFT
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
+2 -2
View File
@@ -40,7 +40,7 @@ public:
// access functions // access functions
[[__noreturn__]] void rethrow_nested() const; [[__noreturn__]] void rethrow_nested() const;
_LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
}; };
template <class _Tp> template <class _Tp>
@@ -73,7 +73,7 @@ template <class _Tp>
__throw_with_nested<_Tp, __throw_with_nested<_Tp,
_Up, _Up,
is_class<_Up>::value && !is_base_of<nested_exception, _Up>::value && is_class<_Up>::value && !is_base_of<nested_exception, _Up>::value &&
!__libcpp_is_final<_Up>::value>::__do_throw(std::forward<_Tp>(__t)); !__is_final_v<_Up> >::__do_throw(std::forward<_Tp>(__t));
#else #else
((void)__t); ((void)__t);
// FIXME: Make this abort // FIXME: Make this abort
+5 -5
View File
@@ -20,22 +20,22 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
defined(_LIBCPP_BUILDING_LIBRARY) defined(_LIBCPP_BUILDING_LIBRARY)
using unexpected_handler = void (*)(); using unexpected_handler = void (*)();
_LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; _LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
_LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT;
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void unexpected(); [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void unexpected();
#endif #endif
using terminate_handler = void (*)(); using terminate_handler = void (*)();
_LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT; _LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
_LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT;
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION) #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT;
#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION) #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
_LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT;
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr; class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD _LIBCPP_END_UNVERSIONED_NAMESPACE_STD

Some files were not shown because too many files have changed in this diff Show More