89 changes: 49 additions & 40 deletions libcxx/include/__algorithm/inplace_merge.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H
#define _LIBCPP___ALGORITHM_INPLACE_MERGE_H

#include <__algorithm/algorithm_family.h>
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h>
Expand Down Expand Up @@ -54,18 +55,17 @@ class __invert // invert the sense of a comparison
bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);}
};

template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2,
class _OutputIterator>
void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
template <class _AlgPolicy, class _Compare, class _InputIterator1, class _Sent1,
class _InputIterator2, class _Sent2, class _OutputIterator>
void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1,
_InputIterator2 __first2, _Sent2 __last2,
_OutputIterator __result, _Compare&& __comp)
{
for (; __first1 != __last1; ++__result)
{
if (__first2 == __last2)
{
// TODO(alg-policy): pass `_AlgPolicy` once it's supported by `move`.
_VSTD::move(__first1, __last1, __result);
_AlgFamily<_AlgPolicy>::__move(__first1, __last1, __result);
return;
}

Expand All @@ -84,21 +84,23 @@ void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
void
__buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
_Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
void __buffered_inplace_merge(
_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last,
_Compare&& __comp,
typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff) {
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);
if (__len1 <= __len2)
{
value_type* __p = __buff;
for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p)
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
std::__half_inplace_merge<_AlgPolicy, _Compare>(__buff, __p, __middle, __last, __first, __comp);
std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp);
}
else
{
Expand All @@ -108,19 +110,22 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator
typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi;
typedef __unconstrained_reverse_iterator<value_type*> _Rv;
typedef __invert<_Compare> _Inverted;
std::__half_inplace_merge<_AlgPolicy, _Inverted>(_Rv(__p), _Rv(__buff),
std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff),
_RBi(__middle), _RBi(__first),
_RBi(__last), _Inverted(__comp));
}
}

template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
void
__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
_Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size)
{
void __inplace_merge(
_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last,
_Compare&& __comp,
typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff,
ptrdiff_t __buff_size) {
using _Ops = _IterOps<_AlgPolicy>;

typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
Expand All @@ -130,7 +135,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
if (__len2 == 0)
return;
if (__len1 <= __buff_size || __len2 <= __buff_size)
return std::__buffered_inplace_merge<_AlgPolicy, _Compare>
return std::__buffered_inplace_merge<_AlgPolicy>
(__first, __middle, __last, __comp, __len1, __len2, __buff);
// shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0
for (; true; ++__first, (void) --__len1)
Expand Down Expand Up @@ -158,8 +163,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
__len21 = __len2 / 2;
__m2 = __middle;
_Ops::advance(__m2, __len21);
// TODO: replace _ClassicAlgPolicy and __identity with _AlgPolicy and projection
__m1 = std::__upper_bound<_ClassicAlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
__m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
__len11 = _Ops::distance(__first, __m1);
}
else
Expand Down Expand Up @@ -187,19 +191,17 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
// merge smaller range with recursive call and larger with tail recursion elimination
if (__len11 + __len21 < __len12 + __len22)
{
std::__inplace_merge<_AlgPolicy, _Compare>(
std::__inplace_merge<_AlgPolicy>(
__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
// _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
__first = __middle;
__middle = __m2;
__len1 = __len12;
__len2 = __len22;
}
else
{
std::__inplace_merge<_AlgPolicy, _Compare>(
std::__inplace_merge<_AlgPolicy>(
__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
// _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
__last = __middle;
__middle = __m1;
__len1 = __len11;
Expand All @@ -208,33 +210,40 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
}
}

template <class _BidirectionalIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY
template <class _AlgPolicy, class _BidirectionalIterator, class _Compare>
_LIBCPP_HIDE_FROM_ABI
void
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
_Compare __comp)
__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
_Compare&& __comp)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
difference_type __len1 = _VSTD::distance(__first, __middle);
difference_type __len2 = _VSTD::distance(__middle, __last);
difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle);
difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last);
difference_type __buf_size = _VSTD::min(__len1, __len2);
// TODO: Remove the use of std::get_temporary_buffer
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
_LIBCPP_SUPPRESS_DEPRECATED_POP
unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
return _VSTD::__inplace_merge<_ClassicAlgPolicy, _Comp_ref>(__first, __middle, __last, __comp, __len1, __len2,
__buf.first, __buf.second);
return std::__inplace_merge<_AlgPolicy>(
std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second);
}

template <class _BidirectionalIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(
_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) {
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
std::__inplace_merge<_ClassicAlgPolicy>(
std::move(__first), std::move(__middle), std::move(__last), static_cast<_Comp_ref>(__comp));
}

template <class _BidirectionalIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_HIDE_FROM_ABI
void
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last)
{
_VSTD::inplace_merge(__first, __middle, __last,
std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last),
__less<typename iterator_traits<_BidirectionalIterator>::value_type>());
}

Expand Down
57 changes: 44 additions & 13 deletions libcxx/include/__algorithm/iterator_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <__iterator/iter_swap.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
#include <__iterator/readable_traits.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <type_traits>
Expand All @@ -34,6 +36,10 @@ struct _RangeAlgPolicy {};

template <>
struct _IterOps<_RangeAlgPolicy> {

template <class _Iter>
using __value_type = iter_value_t<_Iter>;

static constexpr auto advance = ranges::advance;
static constexpr auto distance = ranges::distance;
static constexpr auto __iter_move = ranges::iter_move;
Expand All @@ -49,6 +55,9 @@ struct _ClassicAlgPolicy {};
template <>
struct _IterOps<_ClassicAlgPolicy> {

template <class _Iter>
using __value_type = typename iterator_traits<_Iter>::value_type;

// advance
template <class _Iter, class _Distance>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
Expand All @@ -63,24 +72,46 @@ struct _IterOps<_ClassicAlgPolicy> {
return std::distance(__first, __last);
}

// iter_move
template <class _Iter>
using __deref_t = decltype(*std::declval<_Iter&>());

template <class _Iter>
using __move_t = decltype(std::move(*std::declval<_Iter&>()));

template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
// Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce.
static __enable_if_t<
is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value,
typename remove_reference< typename iterator_traits<__uncvref_t<_Iter> >::reference >::type&&>
__iter_move(_Iter&& __i) {
static void __validate_iter_reference() {
static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__uncvref_t<_Iter> >::reference>::value,
"It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of "
"dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] "
"and can lead to dangling reference issues at runtime, so we are flagging this.");
}

// iter_move
template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static
// If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note
// that the C++03 mode doesn't support `decltype(auto)` as the return type.
__enable_if_t<
is_reference<__deref_t<_Iter> >::value,
__move_t<_Iter> >
__iter_move(_Iter&& __i) {
__validate_iter_reference<_Iter>();

return std::move(*std::forward<_Iter>(__i));
}

template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
// Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce.
static __enable_if_t<
!is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value,
typename iterator_traits<__uncvref_t<_Iter> >::reference>
__iter_move(_Iter&& __i) {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static
// If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a
// value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that
// temporary. Note that the C++03 mode doesn't support `auto` as the return type.
__enable_if_t<
!is_reference<__deref_t<_Iter> >::value,
__deref_t<_Iter> >
__iter_move(_Iter&& __i) {
__validate_iter_reference<_Iter>();

return *std::forward<_Iter>(__i);
}

Expand All @@ -100,7 +131,7 @@ struct _IterOps<_ClassicAlgPolicy> {

template <class _Iter>
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
__uncvref_t<_Iter> next(_Iter&& __it,
__uncvref_t<_Iter> next(_Iter&& __it,
typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){
return std::next(std::forward<_Iter>(__it), __n);
}
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__algorithm/make_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
using _CompRef = typename __comp_ref_type<_Compare>::type;
_CompRef __comp_ref = __comp;

Expand All @@ -34,7 +34,7 @@ void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _C
if (__n > 1) {
// 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, _CompRef>(__first, __comp_ref, __n, __first + __start);
std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start);
}
}
}
Expand Down
98 changes: 69 additions & 29 deletions libcxx/include/__algorithm/make_projected.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,91 @@
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__type_traits/decay.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_member_pointer.h>
#include <__type_traits/is_same.h>
#include <__utility/declval.h>
#include <__utility/forward.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)

_LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {

template <class _Pred, class _Proj>
_LIBCPP_HIDE_FROM_ABI constexpr static
decltype(auto) __make_projected_pred(_Pred& __pred, _Proj& __proj) {
if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Pred>>) {
// Avoid creating the lambda and just use the pristine predicate -- for certain algorithms, this would enable
// optimizations that rely on the type of the predicate.
return __pred;
struct _ProjectedPred {
_Pred& __pred; // Can be a unary or a binary predicate.
_Proj& __proj;

_LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {}

template <class _Tp>
typename __invoke_of<_Pred&,
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))
>::type
_LIBCPP_CONSTEXPR operator()(_Tp&& __v) const {
return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v)));
}

} else {
return [&](auto&& __x) {
return std::invoke(__pred, std::invoke(__proj, std::forward<decltype(__x)>(__x)));
};
template <class _T1, class _T2>
typename __invoke_of<_Pred&,
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))
>::type
_LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const {
return std::__invoke(__pred,
std::__invoke(__proj, std::forward<_T1>(__lhs)),
std::__invoke(__proj, std::forward<_T2>(__rhs)));
}
}

template <class _Comp, class _Proj>
_LIBCPP_HIDE_FROM_ABI constexpr static
decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) {
if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Comp>>) {
// Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable
// optimizations that rely on the type of the comparator.
return __comp;
};

} else {
return [&](auto&& __lhs, auto&& __rhs) {
return std::invoke(__comp,
std::invoke(__proj, std::forward<decltype(__lhs)>(__lhs)),
std::invoke(__proj, std::forward<decltype(__rhs)>(__rhs)));
};
}
template <class _Pred, class _Proj, class = void>
struct __can_use_pristine_comp : false_type {};

template <class _Pred, class _Proj>
struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t<
!is_member_pointer<typename decay<_Pred>::type>::value && (
#if _LIBCPP_STD_VER > 17
is_same<typename decay<_Proj>::type, identity>::value ||
#endif
is_same<typename decay<_Proj>::type, __identity>::value
)
> > : true_type {};

template <class _Pred, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static
__enable_if_t<
!__can_use_pristine_comp<_Pred, _Proj>::value,
_ProjectedPred<_Pred, _Proj>
>
__make_projected(_Pred& __pred, _Proj& __proj) {
return _ProjectedPred<_Pred, _Proj>(__pred, __proj);
}

// Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable
// optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in
// the call stack when the comparator is invoked, even in an unoptimized build.
template <class _Pred, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static
__enable_if_t<
__can_use_pristine_comp<_Pred, _Proj>::value,
_Pred&
>
__make_projected(_Pred& __pred, _Proj&) {
return __pred;
}

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)

_LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {

template <class _Comp, class _Proj1, class _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr static
decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
Expand Down
10 changes: 5 additions & 5 deletions libcxx/include/__algorithm/partial_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_AFTER_CXX17
_RandomAccessIterator __partial_sort_impl(
_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare __comp) {
_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) {
if (__first == __middle) {
return _IterOps<_AlgPolicy>::next(__middle, __last);
}

std::__make_heap<_AlgPolicy, _Compare>(__first, __middle, __comp);
std::__make_heap<_AlgPolicy>(__first, __middle, __comp);

typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first;
_RandomAccessIterator __i = __middle;
Expand All @@ -45,11 +45,11 @@ _RandomAccessIterator __partial_sort_impl(
if (__comp(*__i, *__first))
{
_IterOps<_AlgPolicy>::iter_swap(__i, __first);
std::__sift_down<_AlgPolicy, _Compare>(__first, __comp, __len, __first);
std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first);
}

}
std::__sort_heap<_AlgPolicy, _Compare>(std::move(__first), std::move(__middle), __comp);
std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp);

return __i;
}
Expand All @@ -64,7 +64,7 @@ _RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAcces
std::__debug_randomize_range<_AlgPolicy>(__first, __last);

using _Comp_ref = typename __comp_ref_type<_Compare>::type;
auto __last_iter = std::__partial_sort_impl<_AlgPolicy, _Comp_ref>(__first, __middle, __last, __comp);
auto __last_iter = std::__partial_sort_impl<_AlgPolicy>(__first, __middle, __last, static_cast<_Comp_ref>(__comp));

std::__debug_randomize_range<_AlgPolicy>(__middle, __last);

Expand Down
42 changes: 29 additions & 13 deletions libcxx/include/__algorithm/partial_sort_copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,50 @@
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_heap.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/sift_down.h>
#include <__algorithm/sort_heap.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/is_callable.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _InputIterator, class _RandomAccessIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator
__partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
template <class _AlgPolicy, class _Compare,
class _InputIterator, class _Sentinel1, class _RandomAccessIterator, class _Sentinel2,
class _Proj1, class _Proj2>
_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator, _RandomAccessIterator>
__partial_sort_copy(_InputIterator __first, _Sentinel1 __last,
_RandomAccessIterator __result_first, _Sentinel2 __result_last,
_Compare&& __comp, _Proj1&& __proj1, _Proj2&& __proj2)
{
_RandomAccessIterator __r = __result_first;
auto&& __projected_comp = std::__make_projected(__comp, __proj2);

if (__r != __result_last)
{
for (; __first != __last && __r != __result_last; ++__first, (void) ++__r)
*__r = *__first;
std::__make_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp);
std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first;
for (; __first != __last; ++__first)
if (__comp(*__first, *__result_first))
{
if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) {
*__result_first = *__first;
std::__sift_down<_AlgPolicy, _Compare>(__result_first, __comp, __len, __result_first);
std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first);
}
std::__sort_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp);
std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
}
return __r;

return pair<_InputIterator, _RandomAccessIterator>(
_IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r));
}

template <class _InputIterator, class _RandomAccessIterator, class _Compare>
Expand All @@ -53,9 +65,13 @@ _RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
{
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
return std::__partial_sort_copy<_ClassicAlgPolicy, _Comp_ref>(
__first, __last, __result_first, __result_last, __comp);
static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value,
"Comparator has to be callable");

using _Comp_ref = typename __comp_ref_type<_Compare>::type;
auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last,
static_cast<_Comp_ref>(__comp), __identity(), __identity());
return __result.second;
}

template <class _InputIterator, class _RandomAccessIterator>
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__algorithm/pop_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
if (__len > 1) {
value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first
_RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __len);
_RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len);
--__last;

if (__hole == __last) {
Expand All @@ -47,7 +47,7 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co
*__hole = _IterOps<_AlgPolicy>::__iter_move(__last);
++__hole;
*__last = std::move(__top);
std::__sift_up<_AlgPolicy, _CompRef>(__first, __hole, __comp_ref, __hole - __first);
std::__sift_up<_AlgPolicy>(__first, __hole, __comp_ref, __hole - __first);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/push_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) {
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;

Expand Down
52 changes: 32 additions & 20 deletions libcxx/include/__algorithm/ranges_inplace_merge.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
#define _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H

#include <__algorithm/inplace_merge.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
#include <__iterator/projected.h>
#include <__iterator/sortable.h>
#include <__ranges/access.h>
Expand All @@ -36,28 +38,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __inplace_merge {

struct __fn {
struct __fn {
template <class _Iter, class _Sent, class _Comp, class _Proj>
_LIBCPP_HIDE_FROM_ABI static constexpr auto
__inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) {
auto __last_iter = ranges::next(__middle, __last);
std::__inplace_merge<_RangeAlgPolicy>(
std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj));
return __last_iter;
}

template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
requires sortable<_Iter, _Comp, _Proj>
_LIBCPP_HIDE_FROM_ABI
_Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__first; (void)__middle; (void)__last; (void)__comp; (void)__proj;
return {};
}
template <
bidirectional_iterator _Iter,
sentinel_for<_Iter> _Sent,
class _Comp = ranges::less,
class _Proj = identity>
requires sortable<_Iter, _Comp, _Proj>
_LIBCPP_HIDE_FROM_ABI _Iter
operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
return __inplace_merge_impl(
std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj));
}

template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
requires sortable<iterator_t<_Range>, _Comp, _Proj>
_LIBCPP_HIDE_FROM_ABI
borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle,
_Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__range; (void)__middle; (void)__comp; (void)__proj;
return {};
}

};
template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
requires sortable<
iterator_t<_Range>,
_Comp,
_Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range>
operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const {
return __inplace_merge_impl(
ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj));
}
};

} // namespace __inplace_merge

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_is_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct __fn {
_LIBCPP_HIDE_FROM_ABI constexpr
static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);

auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp);
return __result == __last;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_is_heap_until.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct __fn {
_LIBCPP_HIDE_FROM_ABI constexpr
static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);

return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp);
}
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_make_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct __fn {
_Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__make_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_nth_element.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct __fn {
_Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__nth_element_impl<_RangeAlgPolicy>(std::move(__first), std::move(__nth), __last_iter, __projected_comp);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_partial_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct __fn {
template <class _Iter, class _Sent, class _Comp, class _Proj>
_LIBCPP_HIDE_FROM_ABI constexpr static
_Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp);
}

Expand Down
19 changes: 11 additions & 8 deletions libcxx/include/__algorithm/ranges_partial_sort_copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
#define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H

#include <__algorithm/in_out_result.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/partial_sort_copy.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
Expand All @@ -23,7 +23,6 @@
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__utility/forward.h>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand Down Expand Up @@ -52,9 +51,11 @@ struct __fn {
partial_sort_copy_result<_Iter1, _Iter2>
operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last,
_Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
// TODO: implement
(void)__first; (void)__last; (void)__result_first; (void)__result_last; (void)__comp; (void)__proj1; (void)__proj2;
return {};
auto __result = std::__partial_sort_copy<_RangeAlgPolicy>(
std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last),
__comp, __proj1, __proj2
);
return {std::move(__result.first), std::move(__result.second)};
}

template <input_range _Range1, random_access_range _Range2, class _Comp = ranges::less,
Expand All @@ -67,9 +68,11 @@ struct __fn {
partial_sort_copy_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>>
operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
// TODO: implement
(void)__range; (void)__result_range; (void)__comp; (void)__proj1; (void)__proj2;
return {};
auto __result = std::__partial_sort_copy<_RangeAlgPolicy>(
ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range),
__comp, __proj1, __proj2
);
return {std::move(__result.first), std::move(__result.second)};
}

};
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct __fn {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI static constexpr
subrange<__uncvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj);
auto&& __projected_pred = std::__make_projected(__pred, __proj);
auto __result = std::__partition<_RangeAlgPolicy>(
std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>());

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_pop_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct __fn {
auto __last_iter = ranges::next(__first, __last);
auto __len = __last_iter - __first;

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_push_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct __fn {
_Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__push_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct __fn {
_Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_sort_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct __fn {
_Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__sort_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);

return __last_iter;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_stable_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct __fn {
_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj);
auto&& __projected_pred = std::__make_projected(__pred, __proj);
auto __result = std::__stable_partition<_RangeAlgPolicy>(
std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>());

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/ranges_stable_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct __fn {
static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);

auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);

return __last_iter;
Expand Down
46 changes: 25 additions & 21 deletions libcxx/include/__algorithm/ranges_unique.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H

#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique.h>
#include <__config>
Expand Down Expand Up @@ -37,28 +38,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __unique {

struct __fn {
struct __fn {
template <
permutable _Iter,
sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__unique<_RangeAlgPolicy>(
std::move(__first), std::move(__last), std::__make_projected(__comp, __proj));
return {std::move(__ret.first), std::move(__ret.second)};
}

template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
_LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__first; (void)__last; (void)__comp; (void)__proj;
return {};
}

template <forward_range _Range, class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
_LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__range; (void)__comp; (void)__proj;
return {};
}

};
template <
forward_range _Range,
class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
_LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__unique<_RangeAlgPolicy>(
ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj));
return {std::move(__ret.first), std::move(__ret.second)};
}
};

} // namespace __unique

Expand Down
73 changes: 50 additions & 23 deletions libcxx/include/__algorithm/ranges_unique_copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H

#include <__algorithm/in_out_result.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique_copy.h>
#include <__concepts/same_as.h>
Expand All @@ -19,8 +20,8 @@
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/readable_traits.h>
#include <__iterator/projected.h>
#include <__iterator/readable_traits.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
Expand All @@ -42,42 +43,68 @@ using unique_copy_result = in_out_result<_InIter, _OutIter>;

namespace __unique_copy {

template <class _InIter, class _OutIter>
concept __can_reread_from_output = (input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>);

struct __fn {
template <class _InIter, class _OutIter>
static consteval auto __get_algo_tag() {
if constexpr (forward_iterator<_InIter>) {
return __unique_copy_tags::__reread_from_input_tag{};
} else if constexpr (__can_reread_from_output<_InIter, _OutIter>) {
return __unique_copy_tags::__reread_from_output_tag{};
} else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) {
return __unique_copy_tags::__read_from_tmp_value_tag{};
}
}

template <class _InIter, class _OutIter>
using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>());

template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter, class _Proj = identity,
template <input_iterator _InIter,
sentinel_for<_InIter> _Sent,
weakly_incrementable _OutIter,
class _Proj = identity,
indirect_equivalence_relation<projected<_InIter, _Proj>> _Comp = ranges::equal_to>
requires indirectly_copyable<_InIter, _OutIter> &&
(forward_iterator<_InIter> ||
(input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<_InIter, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr
unique_copy_result<_InIter, _OutIter>
requires indirectly_copyable<_InIter, _OutIter> &&
(forward_iterator<_InIter> ||
(input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<_InIter, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter>
operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__first; (void)__last; (void)__result; (void)__comp; (void)__proj;
return {};
auto __ret = std::__unique_copy<_RangeAlgPolicy>(
std::move(__first),
std::move(__last),
std::move(__result),
std::__make_projected(__comp, __proj),
__algo_tag_t<_InIter, _OutIter>());
return {std::move(__ret.first), std::move(__ret.second)};
}

template <input_range _Range, weakly_incrementable _OutIter, class _Proj = identity,
template <input_range _Range,
weakly_incrementable _OutIter,
class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
(forward_iterator<iterator_t<_Range>> ||
(input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr
unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
(forward_iterator<iterator_t<_Range>> ||
(input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__range; (void)__result; (void)__comp; (void)__proj;
return {};
auto __ret = std::__unique_copy<_RangeAlgPolicy>(
ranges::begin(__range),
ranges::end(__range),
std::move(__result),
std::__make_projected(__comp, __proj),
__algo_tag_t<iterator_t<_Range>, _OutIter>());
return {std::move(__ret.first), std::move(__ret.second)};
}

};

} // namespace __unique_copy

inline namespace __cpo {
inline constexpr auto unique_copy = __unique_copy::__fn{};
inline constexpr auto unique_copy = __unique_copy::__fn{};
} // namespace __cpo
} // namespace ranges

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__algorithm/sift_down.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX11 void
__sift_down(_RandomAccessIterator __first, _Compare __comp,
__sift_down(_RandomAccessIterator __first, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
_RandomAccessIterator __start)
{
Expand Down Expand Up @@ -79,7 +79,7 @@ __sift_down(_RandomAccessIterator __first, _Compare __comp,

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator
__floyd_sift_down(_RandomAccessIterator __first, _Compare __comp,
__floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len)
{
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__algorithm/sort_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
using _CompRef = typename __comp_ref_type<_Compare>::type;
_CompRef __comp_ref = __comp;

using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n)
std::__pop_heap<_AlgPolicy, _CompRef>(__first, __last, __comp_ref, __n);
std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n);
}

template <class _RandomAccessIterator, class _Compare>
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/stable_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp
}
std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size);
std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size);
std::__inplace_merge<_AlgPolicy, _Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
}

template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
Expand Down
48 changes: 26 additions & 22 deletions libcxx/include/__algorithm/unique.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

#include <__algorithm/adjacent_find.h>
#include <__algorithm/comp.h>
#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -23,32 +25,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// unique

template <class _AlgPolicy, class _Iter, class _Sent, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 std::pair<_Iter, _Iter>
__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
__first = std::__adjacent_find(__first, __last, __pred);
if (__first != __last) {
// ... a a ? ...
// f i
_Iter __i = __first;
for (++__i; ++__i != __last;)
if (!__pred(*__first, *__i))
*++__first = _IterOps<_AlgPolicy>::__iter_move(__i);
++__first;
return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i));
}
return std::pair<_Iter, _Iter>(__first, __first);
}

template <class _ForwardIterator, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
{
__first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred);
if (__first != __last)
{
// ... a a ? ...
// f i
_ForwardIterator __i = __first;
for (++__i; ++__i != __last;)
if (!__pred(*__first, *__i))
*++__first = _VSTD::move(*__i);
++__first;
}
return __first;
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first;
}

template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last)
{
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
return _VSTD::unique(__first, __last, __equal_to<__v>());
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last) {
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
return std::unique(__first, __last, __equal_to<__v>());
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
147 changes: 82 additions & 65 deletions libcxx/include/__algorithm/unique_copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,97 +10,114 @@
#define _LIBCPP___ALGORITHM_UNIQUE_COPY_H

#include <__algorithm/comp.h>
#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__type_traits/conditional.h>
#include <__type_traits/is_base_of.h>
#include <__type_traits/is_same.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _BinaryPredicate, class _InputIterator, class _OutputIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
__unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred,
input_iterator_tag, output_iterator_tag)
{
if (__first != __last)
{
typename iterator_traits<_InputIterator>::value_type __t(*__first);
namespace __unique_copy_tags {

struct __reread_from_input_tag {};
struct __reread_from_output_tag {};
struct __read_from_tmp_value_tag {};

} // namespace __unique_copy_tags

template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _OutputIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator>
__unique_copy(_InputIterator __first,
_Sent __last,
_OutputIterator __result,
_BinaryPredicate&& __pred,
__unique_copy_tags::__read_from_tmp_value_tag) {
if (__first != __last) {
typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first);
*__result = __t;
++__result;
while (++__first != __last) {
if (!__pred(__t, *__first)) {
__t = *__first;
*__result = __t;
++__result;
while (++__first != __last)
{
if (!__pred(__t, *__first))
{
__t = *__first;
*__result = __t;
++__result;
}
}
}
}
return __result;
}
return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result));
}

template <class _BinaryPredicate, class _ForwardIterator, class _OutputIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
__unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred,
forward_iterator_tag, output_iterator_tag)
{
if (__first != __last)
{
_ForwardIterator __i = __first;
*__result = *__i;
template <class _AlgPolicy, class _BinaryPredicate, class _ForwardIterator, class _Sent, class _OutputIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator>
__unique_copy(_ForwardIterator __first,
_Sent __last,
_OutputIterator __result,
_BinaryPredicate&& __pred,
__unique_copy_tags::__reread_from_input_tag) {
if (__first != __last) {
_ForwardIterator __i = __first;
*__result = *__i;
++__result;
while (++__first != __last) {
if (!__pred(*__i, *__first)) {
*__result = *__first;
++__result;
while (++__first != __last)
{
if (!__pred(*__i, *__first))
{
*__result = *__first;
++__result;
__i = __first;
}
}
__i = __first;
}
}
return __result;
}
return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result));
}

template <class _BinaryPredicate, class _InputIterator, class _ForwardIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
__unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred,
input_iterator_tag, forward_iterator_tag)
{
if (__first != __last)
{
*__result = *__first;
while (++__first != __last)
if (!__pred(*__result, *__first))
*++__result = *__first;
++__result;
}
return __result;
template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _InputAndOutputIterator>
_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator>
__unique_copy(_InputIterator __first,
_Sent __last,
_InputAndOutputIterator __result,
_BinaryPredicate&& __pred,
__unique_copy_tags::__reread_from_output_tag) {
if (__first != __last) {
*__result = *__first;
while (++__first != __last)
if (!__pred(*__result, *__first))
*++__result = *__first;
++__result;
}
return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result));
}

template <class _InputIterator, class _OutputIterator, class _BinaryPredicate>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred)
{
return _VSTD::__unique_copy<_BinaryPredicate&>(__first, __last, __result, __pred,
typename iterator_traits<_InputIterator>::iterator_category(),
typename iterator_traits<_OutputIterator>::iterator_category());
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) {
using __algo_tag = typename conditional<
is_base_of<forward_iterator_tag, typename iterator_traits<_InputIterator>::iterator_category>::value,
__unique_copy_tags::__reread_from_input_tag,
typename conditional<
is_base_of<forward_iterator_tag, typename iterator_traits<_OutputIterator>::iterator_category>::value &&
is_same< typename iterator_traits<_InputIterator>::value_type,
typename iterator_traits<_OutputIterator>::value_type>::value,
__unique_copy_tags::__reread_from_output_tag,
__unique_copy_tags::__read_from_tmp_value_tag>::type >::type;
return std::__unique_copy<_ClassicAlgPolicy>(
std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag())
.second;
}

template <class _InputIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
typedef typename iterator_traits<_InputIterator>::value_type __v;
return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>());
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
typedef typename iterator_traits<_InputIterator>::value_type __v;
return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to<__v>());
}


_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H
97 changes: 97 additions & 0 deletions libcxx/include/__algorithm/unwrap_range.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===----------------------------------------------------------------------===//
//
// 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_UNWRAP_RANGE_H
#define _LIBCPP___ALGORITHM_UNWRAP_RANGE_H

#include <__algorithm/unwrap_iter.h>
#include <__concepts/constructible.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/next.h>
#include <__utility/declval.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

// __unwrap_range and __rewrap_range are used to unwrap ranges which may have different iterator and sentinel types.
// __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have
// the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter.

#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
template <class _Iter, class _Sent>
struct __unwrap_range_impl {
_LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent)
requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>
{
auto __last = ranges::next(__first, __sent);
return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))};
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __last) {
return pair{std::move(__first), std::move(__last)};
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto
__rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter)
requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>
{
return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto __rewrap(const _Iter&, _Iter __iter)
requires (!(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>))
{
return __iter;
}
};

template <class _Iter>
struct __unwrap_range_impl<_Iter, _Iter> {
_LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Iter __last) {
return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))};
}

_LIBCPP_HIDE_FROM_ABI static constexpr auto
__rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) {
return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
}
};

template <class _Iter, class _Sent>
_LIBCPP_HIDE_FROM_ABI constexpr auto __unwrap_range(_Iter __first, _Sent __last) {
return __unwrap_range_impl<_Iter, _Sent>::__unwrap(std::move(__first), std::move(__last));
}

template <
class _Sent,
class _Iter,
class _Unwrapped = decltype(std::__unwrap_range(std::declval<_Iter>(), std::declval<_Sent>()))>
_LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) {
return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter));
}
#else // _LIBCPP_STD_VER > 17
template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declval<_Iter>()))>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) {
return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last)));
}

template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declval<_Iter>()))>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) {
return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
}
#endif // _LIBCPP_STD_VER > 17

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___ALGORITHM_UNWRAP_RANGE_H
11 changes: 2 additions & 9 deletions libcxx/include/__assert
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#ifndef _LIBCPP___ASSERT
#define _LIBCPP___ASSERT

#include <__availability>
#include <__config>
#include <__verbose_abort>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand Down Expand Up @@ -45,7 +45,7 @@
# define _LIBCPP_ASSERT(expression, message) \
(__builtin_expect(static_cast<bool>(expression), 1) ? \
(void)0 : \
::std::__libcpp_assertion_handler("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message))
::std::__libcpp_verbose_abort("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message))
#elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume)
# define _LIBCPP_ASSERT(expression, message) \
(_LIBCPP_DIAGNOSTIC_PUSH \
Expand All @@ -56,11 +56,4 @@
# define _LIBCPP_ASSERT(expression, message) ((void)0)
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ASSERTION_HANDLER _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2)
void __libcpp_assertion_handler(const char *__format, ...);

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___ASSERT
41 changes: 20 additions & 21 deletions libcxx/include/__availability
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,21 @@
# define _LIBCPP_AVAILABILITY_FORMAT
// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format

// This controls whether the std::__libcpp_assertion_handler default
// assertion handler is provided by the library.
// This controls whether the default verbose termination function is
// provided by the library.
//
// Note that when users provide their own custom assertion handler,
// it doesn't matter whether the dylib provides a default handler,
// and the availability markup can actually give a false positive
// diagnostic (it will think that no handler is provided, when in
// reality the user has provided their own).
// Note that when users provide their own custom function, it doesn't
// matter whether the dylib provides a default function, and the
// availability markup can actually give a false positive diagnostic
// (it will think that no function is provided, when in reality the
// user has provided their own).
//
// Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED
// Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED
// to the compiler to tell the library to ignore the fact that the
// default handler isn't available on their deployment target. Note that
// defining this macro but failing to define a custom assertion handler
// will lead to a load-time error on back-deployment targets, so it
// should be avoided.
# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER
// default function isn't available on their deployment target. Note that
// defining this macro but failing to define a custom function will lead to
// a load-time error on back-deployment targets, so it should be avoided.
# define _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT

#elif defined(__APPLE__)

Expand Down Expand Up @@ -272,7 +271,7 @@
__attribute__((unavailable))
# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format

# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER \
# define _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT \
__attribute__((unavailable))
#else

Expand All @@ -297,14 +296,14 @@
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
#endif

// Define the special assertion handler availability attribute, which can be silenced by
// users if they provide their own custom assertion handler. The rest of the code should
// not use the *_DEFAULT_* macro directly, since that would make it ignore the fact that
// the user provided a custom handler.
#if defined(_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED)
# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER /* nothing */
// Define the special verbose termination function availability attribute, which can be silenced by
// users if they provide their own custom function. The rest of the code should not use the
// *_DEFAULT_* macro directly, since that would make it ignore the fact that the user provided
// a custom function.
#if defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED)
# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT /* nothing */
#else
# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER
# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT
#endif

#endif // _LIBCPP___AVAILABILITY
4 changes: 1 addition & 3 deletions libcxx/include/__iterator/reverse_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
typename iterator_traits<_Iter>::iterator_category>;
using pointer = typename iterator_traits<_Iter>::pointer;
#if _LIBCPP_STD_VER > 17
using iterator_concept = _If<__is_cpp17_random_access_iterator<_Iter>::value,
random_access_iterator_tag,
bidirectional_iterator_tag>;
using iterator_concept = _If<random_access_iterator<_Iter>, random_access_iterator_tag, bidirectional_iterator_tag>;
using value_type = iter_value_t<_Iter>;
using difference_type = iter_difference_t<_Iter>;
using reference = iter_reference_t<_Iter>;
Expand Down
27 changes: 27 additions & 0 deletions libcxx/include/__verbose_abort
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___VERBOSE_ABORT
#define _LIBCPP___VERBOSE_ABORT

#include <__availability>
#include <__config>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2)
void __libcpp_verbose_abort(const char *__format, ...);

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___VERBOSE_ABORT
70 changes: 66 additions & 4 deletions libcxx/include/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,25 @@ namespace ranges {
indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {}); // since C++20
template<input_iterator I1, sentinel_for<I1> S1,
random_access_iterator I2, sentinel_for<I2> S2,
class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity>
requires indirectly_copyable<I1, I2> && sortable<I2, Comp, Proj2> &&
indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
constexpr partial_sort_copy_result<I1, I2>
partial_sort_copy(I1 first, S1 last, I2 result_first, S2 result_last,
Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20
template<input_range R1, random_access_range R2, class Comp = ranges::less,
class Proj1 = identity, class Proj2 = identity>
requires indirectly_copyable<iterator_t<R1>, iterator_t<R2>> &&
sortable<iterator_t<R2>, Comp, Proj2> &&
indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>,
projected<iterator_t<R2>, Proj2>>
constexpr partial_sort_copy_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>
partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {},
Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20
template<forward_iterator I, sentinel_for<I> S, class Proj = identity,
indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less>
constexpr bool ranges::is_sorted(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20
Expand Down Expand Up @@ -803,7 +822,7 @@ namespace ranges {
set_symmetric_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result,
Comp comp = {}, Proj1 proj1 = {},
Proj2 proj2 = {}); // since C++20
template<input_range R1, input_range R2, weakly_incrementable O,
class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity>
requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2>
Expand All @@ -816,13 +835,13 @@ namespace ranges {
indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less>
constexpr subrange<I>
equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20
template<forward_range R, class T, class Proj = identity,
indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp =
ranges::less>
constexpr borrowed_subrange_t<R>
equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20
template<class I1, class I2, class O>
using set_union_result = in_in_out_result<I1, I2, O>; // since C++20
Expand All @@ -847,13 +866,52 @@ namespace ranges {
ranges::less>
constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {},
Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20
template<input_range R1, input_range R2, class Proj1 = identity,
class Proj2 = identity,
indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>,
projected<iterator_t<R2>, Proj2>> Comp = ranges::less>
constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {},
Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20
template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less,
class Proj = identity>
requires sortable<I, Comp, Proj>
I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20
template<bidirectional_range R, class Comp = ranges::less, class Proj = identity>
requires sortable<iterator_t<R>, Comp, Proj>
borrowed_iterator_t<R>
inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {},
Proj proj = {}); // Since C++20
template<permutable I, sentinel_for<I> S, class Proj = identity,
indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to>
constexpr subrange<I> unique(I first, S last, C comp = {}, Proj proj = {}); // Since C++20
template<forward_range R, class Proj = identity,
indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to>
requires permutable<iterator_t<R>>
constexpr borrowed_subrange_t<R>
unique(R&& r, C comp = {}, Proj proj = {}); // Since C++20
template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity,
indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to>
requires indirectly_copyable<I, O> &&
(forward_iterator<I> ||
(input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>) ||
indirectly_copyable_storable<I, O>)
constexpr unique_copy_result<I, O>
unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); // Since C++20
template<input_range R, weakly_incrementable O, class Proj = identity,
indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to>
requires indirectly_copyable<iterator_t<R>, O> &&
(forward_iterator<iterator_t<R>> ||
(input_iterator<O> && same_as<range_value_t<R>, iter_value_t<O>>) ||
indirectly_copyable_storable<iterator_t<R>, O>)
constexpr unique_copy_result<borrowed_iterator_t<R>, O>
unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // Since C++20
}
constexpr bool // constexpr in C++20
Expand Down Expand Up @@ -1607,6 +1665,7 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/ranges_generate.h>
#include <__algorithm/ranges_generate_n.h>
#include <__algorithm/ranges_includes.h>
#include <__algorithm/ranges_inplace_merge.h>
#include <__algorithm/ranges_is_heap.h>
#include <__algorithm/ranges_is_heap_until.h>
#include <__algorithm/ranges_is_partitioned.h>
Expand All @@ -1628,6 +1687,7 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/ranges_none_of.h>
#include <__algorithm/ranges_nth_element.h>
#include <__algorithm/ranges_partial_sort.h>
#include <__algorithm/ranges_partial_sort_copy.h>
#include <__algorithm/ranges_partition.h>
#include <__algorithm/ranges_partition_copy.h>
#include <__algorithm/ranges_partition_point.h>
Expand All @@ -1653,6 +1713,8 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/ranges_stable_sort.h>
#include <__algorithm/ranges_swap_ranges.h>
#include <__algorithm/ranges_transform.h>
#include <__algorithm/ranges_unique.h>
#include <__algorithm/ranges_unique_copy.h>
#include <__algorithm/ranges_upper_bound.h>
#include <__algorithm/remove.h>
#include <__algorithm/remove_copy.h>
Expand Down
3 changes: 3 additions & 0 deletions libcxx/include/module.modulemap.in
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ module std [system] {

module __algorithm {
module adjacent_find { private header "__algorithm/adjacent_find.h" }
module algorithm_family { private header "__algorithm/algorithm_family.h" }
module all_of { private header "__algorithm/all_of.h" }
module any_of { private header "__algorithm/any_of.h" }
module binary_search { private header "__algorithm/binary_search.h" }
Expand Down Expand Up @@ -419,6 +420,7 @@ module std [system] {
module unique { private header "__algorithm/unique.h" }
module unique_copy { private header "__algorithm/unique_copy.h" }
module unwrap_iter { private header "__algorithm/unwrap_iter.h" }
module unwrap_range { private header "__algorithm/unwrap_range.h" }
module upper_bound { private header "__algorithm/upper_bound.h" }
}
}
Expand Down Expand Up @@ -1292,6 +1294,7 @@ module std [system] {
module __tree { header "__tree" export * }
module __tuple { private header "__tuple" export * }
module __undef_macros { header "__undef_macros" export * }
module __verbose_abort { header "__verbose_abort" export * }

module experimental {
requires cplusplus11
Expand Down
4 changes: 2 additions & 2 deletions libcxx/lib/abi/CHANGELOG.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Version 15.0
Symbol removed: _ZTSNSt3__18__c_nodeE
Symbol removed: _ZTVNSt3__18__c_nodeE

* b0fd9497af6d and 7de5aca84c54 - [libc++] Add a lightweight overridable assertion handler
* b0fd9497af6d, 7de5aca84c54 and XXXXXXXX - [libc++] Add a lightweight overridable assertion handler

This patch adds a lightweight assertion handler mechanism that can be
overriden at link-time in a fashion similar to `operator new`. A default
Expand All @@ -73,7 +73,7 @@ Version 15.0

All platforms
-------------
Symbol added: _ZNSt3__126__libcpp_assertion_handlerEPKcz
Symbol added: _ZNSt3__122__libcpp_verbose_abortEPKcz

------------
Version 14.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,7 @@
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,7 @@
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}
Expand Down
2 changes: 1 addition & 1 deletion libcxx/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTOR
set(LIBCXX_SOURCES
algorithm.cpp
any.cpp
assert.cpp
atomic.cpp
barrier.cpp
bind.cpp
Expand Down Expand Up @@ -62,6 +61,7 @@ set(LIBCXX_SOURCES
valarray.cpp
variant.cpp
vector.cpp
verbose_abort.cpp
)

if (LIBCXX_ENABLE_DEBUG_MODE OR LIBCXX_ENABLE_BACKWARDS_COMPATIBILITY_DEBUG_MODE_SYMBOLS)
Expand Down
22 changes: 17 additions & 5 deletions libcxx/src/assert.cpp → libcxx/src/verbose_abort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@
//
//===----------------------------------------------------------------------===//

#include <__assert>
#include <__config>
#include <__verbose_abort>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>

#ifdef __BIONIC__
# include <android/api-level.h>
# include <syslog.h>
# if __ANDROID_API__ >= 21
# include <syslog.h>
extern "C" void android_set_abort_message(const char* msg);
#endif
# else
# include <assert.h>
# endif // __ANDROID_API__ >= 21
#endif // __BIONIC__

#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
# include <CrashReporterClient.h>
Expand All @@ -25,7 +29,7 @@ extern "C" void android_set_abort_message(const char* msg);
_LIBCPP_BEGIN_NAMESPACE_STD

_LIBCPP_WEAK
void __libcpp_assertion_handler(char const* format, ...) {
void __libcpp_verbose_abort(char const* format, ...) {
// Write message to stderr. We do this before formatting into a
// buffer so that we still get some information out if that fails.
{
Expand All @@ -48,14 +52,22 @@ void __libcpp_assertion_handler(char const* format, ...) {
vasprintf(&buffer, format, list);
CRSetCrashLogMessage(buffer);
#elif defined(__BIONIC__)
// Show error in tombstone.
vasprintf(&buffer, format, list);

# if __ANDROID_API__ >= 21
// Show error in tombstone.
android_set_abort_message(buffer);

// Show error in logcat.
openlog("libc++", 0, 0);
syslog(LOG_CRIT, "%s", buffer);
closelog();
# else
// The good error reporting wasn't available in Android until L. Since we're
// about to abort anyway, just call __assert2, which will log _somewhere_
// (tombstone and/or logcat) in older releases.
__assert2(__FILE__, __LINE__, __func__, buffer);
# endif // __ANDROID_API__ >= 21
#endif
va_end(list);

Expand Down
61 changes: 61 additions & 0 deletions libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// std::sort

#include <algorithm>
#include <iterator>
#include <type_traits>
#include <utility>

struct BadIter {
struct Value {
friend bool operator==(const Value& x, const Value& y);
friend bool operator!=(const Value& x, const Value& y);
friend bool operator< (const Value& x, const Value& y);
friend bool operator<=(const Value& x, const Value& y);
friend bool operator> (const Value& x, const Value& y);
friend bool operator>=(const Value& x, const Value& y);
friend void swap(Value, Value);
};

using iterator_category = std::random_access_iterator_tag;
using value_type = Value;
using reference = Value&;
using difference_type = long;
using pointer = Value*;

Value operator*() const; // Not `Value&`.
reference operator[](difference_type n) const;

BadIter& operator++();
BadIter& operator--();
BadIter operator++(int);
BadIter operator--(int);

BadIter& operator+=(difference_type n);
BadIter& operator-=(difference_type n);
friend BadIter operator+(BadIter x, difference_type n);
friend BadIter operator+(difference_type n, BadIter x);
friend BadIter operator-(BadIter x, difference_type n);
friend difference_type operator-(BadIter x, BadIter y);

friend bool operator==(const BadIter& x, const BadIter& y);
friend bool operator!=(const BadIter& x, const BadIter& y);
friend bool operator< (const BadIter& x, const BadIter& y);
friend bool operator<=(const BadIter& x, const BadIter& y);
friend bool operator> (const BadIter& x, const BadIter& y);
friend bool operator>=(const BadIter& x, const BadIter& y);
};

// Verify that iterators with incorrect `iterator_traits` are rejected. This protects against potential undefined
// behavior when these iterators are passed to standard algorithms.
void test() {
std::sort(BadIter(), BadIter());
//expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of dereferencing the iterator}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ constexpr bool all_the_algorithms()
(void)std::ranges::is_sorted(a, Less(&copies)); assert(copies == 0);
(void)std::ranges::is_sorted_until(first, last, Less(&copies)); assert(copies == 0);
(void)std::ranges::is_sorted_until(a, Less(&copies)); assert(copies == 0);
//if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); }
//if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); }
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); }
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); }
(void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0);
(void)std::ranges::lexicographical_compare(a, b, Less(&copies)); assert(copies == 0);
(void)std::ranges::lower_bound(first, last, value, Less(&copies)); assert(copies == 0);
Expand Down Expand Up @@ -173,8 +173,8 @@ constexpr bool all_the_algorithms()
(void)std::ranges::nth_element(a, mid, Less(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort(first, mid, last, Less(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort(a, mid, Less(&copies)); assert(copies == 0);
//(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0);
//(void)std::ranges::partial_sort_copy(a, b, Less(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort_copy(a, b, Less(&copies)); assert(copies == 0);
(void)std::ranges::partition(first, last, UnaryTrue(&copies)); assert(copies == 0);
(void)std::ranges::partition(a, UnaryTrue(&copies)); assert(copies == 0);
(void)std::ranges::partition_copy(first, last, first2, last2, UnaryTrue(&copies)); assert(copies == 0);
Expand Down Expand Up @@ -222,10 +222,10 @@ constexpr bool all_the_algorithms()
(void)std::ranges::transform(a, first2, UnaryTransform(&copies)); assert(copies == 0);
(void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(&copies)); assert(copies == 0);
(void)std::ranges::transform(a, b, first2, BinaryTransform(&copies)); assert(copies == 0);
//(void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0);
//(void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0);
//(void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0);
//(void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0);
(void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0);
(void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0);
(void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0);
(void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0);
(void)std::ranges::upper_bound(first, last, value, Less(&copies)); assert(copies == 0);
(void)std::ranges::upper_bound(a, value, Less(&copies)); assert(copies == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ constexpr bool all_the_algorithms()
(void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0);
//if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); }
//if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); }
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); }
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); }
(void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
Expand Down Expand Up @@ -156,8 +156,8 @@ constexpr bool all_the_algorithms()
(void)std::ranges::nth_element(a, mid, Less(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort(first, mid, last, Less(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort(a, mid, Less(), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::partial_sort_copy(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partial_sort_copy(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partition(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partition(a, UnaryTrue(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::partition_copy(first, last, first2, last2, UnaryTrue(), Proj(&copies)); assert(copies == 0);
Expand Down Expand Up @@ -213,10 +213,10 @@ constexpr bool all_the_algorithms()
(void)std::ranges::transform(a, first2, UnaryTransform(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0);
(void)std::ranges::transform(a, b, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0);
//(void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::upper_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0);
(void)std::ranges::upper_bound(a, value, Less(), Proj(&copies)); assert(copies == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
//===----------------------------------------------------------------------===//

// Make sure that we can enable assertions when we back-deploy to older platforms
// if we define _LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED.
// if we define _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED.
//
// Note that this test isn't really different from customize_handler.pass.cpp when
// run outside of back-deployment scenarios, but we still run it all the time.

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED

#include <cassert>

bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, ...) {
void std::__libcpp_verbose_abort(char const*, ...) {
handler_called = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
//
//===----------------------------------------------------------------------===//

// Test that we can set a custom assertion handler.
// Test that we can set a custom verbose termination function.

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1

// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime
// We flag uses of the verbose termination function in older dylibs at compile-time to avoid runtime
// failures when back-deploying.
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}

#include <cassert>

bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, ...) {
void std::__libcpp_verbose_abort(char const*, ...) {
handler_called = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <cassert>

bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, ...) {
void std::__libcpp_verbose_abort(char const*, ...) {
handler_called = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

// Make sure that we diagnose any usage of the default assertion handler on a platform
// that doesn't support it at compile-time.
// Make sure that we diagnose any usage of the default verbose termination function
// on a platform that doesn't support it at compile-time.

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1

Expand All @@ -16,5 +16,5 @@
#include <version> // any header would work

void f() {
_LIBCPP_ASSERT(true, "message"); // expected-error {{'__libcpp_assertion_handler' is unavailable}}
_LIBCPP_ASSERT(true, "message"); // expected-error {{'__libcpp_verbose_abort' is unavailable}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//

// Test that the default assertion handler aborts the program.
// Test that the default verbose termination function aborts the program.

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1

// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime
// We flag uses of the verbose termination function in older dylibs at compile-time to avoid runtime
// failures when back-deploying.
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}

Expand Down
Loading