Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm-project
Submodule llvm-project updated 8490 files
381 changes: 346 additions & 35 deletions stl/inc/algorithm

Large diffs are not rendered by default.

155 changes: 43 additions & 112 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,28 @@ concept indirect_binary_predicate = indirectly_readable<_It1>
&& predicate<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>>
&& predicate<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;

// CONCEPT indirect_equivalence_relation
template <class _Fn, class _It1, class _It2 = _It1>
concept indirect_equivalence_relation = indirectly_readable<_It1>
&& indirectly_readable<_It2>
&& copy_constructible<_Fn>
&& equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&>
&& equivalence_relation<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>>
&& equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&>
&& equivalence_relation<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>>
&& equivalence_relation<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;

// CONCEPT indirect_strict_weak_order
template <class _Fn, class _It1, class _It2 = _It1>
concept indirect_strict_weak_order = indirectly_readable<_It1>
&& indirectly_readable<_It2>
&& copy_constructible<_Fn>
&& strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_value_t<_It2>&>
&& strict_weak_order<_Fn&, iter_value_t<_It1>&, iter_reference_t<_It2>>
&& strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_value_t<_It2>&>
&& strict_weak_order<_Fn&, iter_reference_t<_It1>, iter_reference_t<_It2>>
&& strict_weak_order<_Fn&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>;

// ALIAS TEMPLATE indirect_result_t
template <class _Fn, class... _Its>
requires (indirectly_readable<_Its> && ...)
Expand Down Expand Up @@ -987,6 +1009,11 @@ namespace ranges {
concept _Can_swap_references = indirectly_readable<remove_reference_t<_Ty1>>
&& indirectly_readable<remove_reference_t<_Ty2>>
&& swappable_with<iter_reference_t<_Ty1>, iter_reference_t<_Ty2>>;

template <class _Ty1, class _Ty2>
concept _Symmetric_indirectly_movable_storable =
indirectly_movable_storable<remove_reference_t<_Ty1>, remove_reference_t<_Ty2>>
&& indirectly_movable_storable<remove_reference_t<_Ty2>, remove_reference_t<_Ty1>>;
// clang-format on

template <class _Xty, class _Yty>
Expand All @@ -1001,15 +1028,13 @@ namespace ranges {
private:
enum class _St { _None, _Custom, _Swap, _Exchange };

// clang-format off
template <class _Ty1, class _Ty2>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (_Has_ADL<_Ty1, _Ty2>) {
return {_St::_Custom, noexcept(iter_swap(_STD declval<_Ty1>(), _STD declval<_Ty2>()))};
} else if constexpr (_Can_swap_references<_Ty1, _Ty2>) {
return {_St::_Swap, noexcept(_RANGES swap(*_STD declval<_Ty1>(), *_STD declval<_Ty2>()))};
} else if constexpr (indirectly_movable_storable<remove_reference_t<_Ty1>, remove_reference_t<_Ty2>>
&& indirectly_movable_storable<remove_reference_t<_Ty2>, remove_reference_t<_Ty1>>) {
} else if constexpr (_Symmetric_indirectly_movable_storable<_Ty1, _Ty2>) {
constexpr auto _Nothrow = noexcept(
*_STD declval<_Ty1>() = _Iter_exchange_move(_STD declval<_Ty1>(), _STD declval<_Ty2>()));
return {_St::_Exchange, _Nothrow};
Expand All @@ -1022,6 +1047,7 @@ namespace ranges {
static constexpr _Choice_t<_St> _Choice = _Choose<_Ty1, _Ty2>();

public:
// clang-format off
template <class _Ty1, class _Ty2>
requires (_Choice<_Ty1, _Ty2>._Strategy != _St::_None)
constexpr void operator()(_Ty1&& _Val1, _Ty2&& _Val2) const noexcept(_Choice<_Ty1, _Ty2>._No_throw) {
Expand Down Expand Up @@ -3261,6 +3287,19 @@ namespace ranges {
// VARIABLE ranges::prev
inline constexpr _Prev_fn prev{_Not_quite_object::_Construct_tag{}};

// FUNCTION TEMPLATE _Find_last_iterator
template <forward_iterator _It, sentinel_for<_It> _Se>
_NODISCARD constexpr _It _Find_last_iterator(
const _It& _First, const _Se& _Last, const iter_difference_t<_It> _Count) {
// Find the iterator in [_First, _Last) (of length _Count) which equals _Last
_STL_INTERNAL_CHECK(_RANGES distance(_First, _Last) == _Count);
if constexpr (is_same_v<_It, _Se>) {
return _Last;
} else {
return _RANGES next(_First, _Count);
}
}

// STRUCT ranges::equal_to
struct equal_to {
// clang-format off
Expand Down Expand Up @@ -5346,7 +5385,7 @@ _NODISCARD _Iter_diff_t<_FwdIt> count(
_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept; // terminates
#endif // _HAS_CXX17

// FUNCTION TEMPLATE is_permutation
// FUNCTION TEMPLATE _Check_match_counts
template <class _InIt, class _Ty, class _Pr>
_NODISCARD constexpr _InIt _Find_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr _Pred) {
for (; _First != _Last; ++_First) {
Expand Down Expand Up @@ -5427,114 +5466,6 @@ _NODISCARD _CONSTEXPR20 bool _Check_match_counts(
return true;
}

template <class _FwdIt1, class _FwdIt2, class _Pr>
_NODISCARD _CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) {
// test if [_First1, _Last1) == permuted [_First2, ...), using _Pred
for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix
if (!_Pred(*_First1, *_First2)) {
// found first inequality, check match counts in suffix
//
// narrowing _Iter_diff_t<_FwdIt1> to _Iter_diff_t<_FwdIt2> is OK because if the second range is shorter
// than the first, the user already triggered UB
auto _Last2 = _STD next(_First2, static_cast<_Iter_diff_t<_FwdIt2>>(_STD distance(_First1, _Last1)));
return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred);
}
}

return true;
}

template <class _FwdIt1, class _FwdIt2, class _Pr>
_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) {
// test if [_First1, _Last1) == permuted [_First2, ...), using _Pred
_Adl_verify_range(_First1, _Last1);
const auto _UFirst1 = _Get_unwrapped(_First1);
const auto _ULast1 = _Get_unwrapped(_Last1);
const auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_FwdIt1>(_UFirst1, _ULast1));
return _Is_permutation_unchecked(_UFirst1, _ULast1, _UFirst2, _Pass_fn(_Pred));
}

template <class _FwdIt1, class _FwdIt2>
_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) {
// test if [_First1, _Last1) == permuted [_First2, ...)
return _STD is_permutation(_First1, _Last1, _First2, equal_to<>());
}

template <class _FwdIt1, class _FwdIt2, class _Pr>
_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred,
forward_iterator_tag, forward_iterator_tag) {
// test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred, arbitrary iterators
for (;;) { // trim matching prefix
if (_First1 == _Last1) {
return _First2 == _Last2;
}

if (_First2 == _Last2) {
return false;
}

if (!_Pred(*_First1, *_First2)) { // found first inequality, check match counts in suffix
break;
}

++_First1;
++_First2;
}

auto _Next1 = _First1;
auto _Next2 = _First2;
for (;;) { // check for same lengths
if (_Next1 == _Last1) {
if (_Next2 == _Last2) {
return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred);
}

return false; // sequence 1 is shorter than sequence 2, not a permutation
}

if (_Next2 == _Last2) {
return false; // sequence 1 is longer than sequence 2, not a permutation
}

++_Next1;
++_Next2;
}
}

template <class _FwdIt1, class _FwdIt2, class _Pr>
_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred,
random_access_iterator_tag, random_access_iterator_tag) {
// test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred, random-access iterators
if (_Last1 - _First1 != _Last2 - _First2) {
return false;
}

for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix
if (!_Pred(*_First1, *_First2)) {
// found first inequality, check match counts in suffix
return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred);
}
}

return true;
}

template <class _FwdIt1, class _FwdIt2, class _Pr>
_NODISCARD _CONSTEXPR20 bool is_permutation(
_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) {
// test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);
return _Is_permutation_unchecked(_Get_unwrapped(_First1), _Get_unwrapped(_Last1), _Get_unwrapped(_First2),
_Get_unwrapped(_Last2), _Pass_fn(_Pred), _Iter_cat_t<_FwdIt1>(), _Iter_cat_t<_FwdIt2>());
}

template <class _FwdIt1, class _FwdIt2>
_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) {
// test if [_First1, _Last1) == permuted [_First2, _Last2)
return _STD is_permutation(_First1, _Last1, _First2, _Last2, equal_to<>());
}

// FUNCTION TEMPLATE reverse
#if _HAS_IF_CONSTEXPR
template <class _BidIt>
Expand Down
4 changes: 2 additions & 2 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -583,11 +583,11 @@ std/containers/sequences/array/array.fill/fill.fail.cpp FAIL
std/containers/sequences/array/array.swap/swap.fail.cpp FAIL

# STL bug: VSO-207715 We reject array<NoDefault, 0>.
std/containers/sequences/array/array.cons/default.pass.cpp FAIL
std/containers/sequences/array/array.cons/implicit_copy.pass.cpp FAIL
std/containers/sequences/array/array.cons/initialization.pass.cpp FAIL
std/containers/sequences/array/array.data/data_const.pass.cpp FAIL
std/containers/sequences/array/array.data/data.pass.cpp FAIL
std/containers/sequences/array/begin.pass.cpp FAIL
std/containers/sequences/array/iterators.pass.cpp FAIL

# STL bug: string_view doesn't enforce "non-array trivial standard-layout", related to LWG-3034.
std/strings/string.view/char.bad.fail.cpp:0 FAIL
Expand Down
6 changes: 3 additions & 3 deletions tests/libcxx/magic_comments.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// REQUIRES: c++03
// REQUIRES: c++03 || c++11 || c++14
// REQUIRES: c++03 || c++11 || c++14 || c++17
// REQUIRES: c++11
// REQUIRES: c++11 || c++14
// REQUIRES: c++98 || c++03
// REQUIRES: c++98 || c++03 || c++11 || c++14
// REQUIRES: c++98 || c++03 || c++11 || c++14 || c++17
// UNSUPPORTED: c++14, c++17, c++2a
4 changes: 2 additions & 2 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -583,11 +583,11 @@ containers\sequences\array\array.fill\fill.fail.cpp
containers\sequences\array\array.swap\swap.fail.cpp

# STL bug: VSO-207715 We reject array<NoDefault, 0>.
containers\sequences\array\array.cons\default.pass.cpp
containers\sequences\array\array.cons\implicit_copy.pass.cpp
containers\sequences\array\array.cons\initialization.pass.cpp
containers\sequences\array\array.data\data_const.pass.cpp
containers\sequences\array\array.data\data.pass.cpp
containers\sequences\array\begin.pass.cpp
containers\sequences\array\iterators.pass.cpp

# STL bug: string_view doesn't enforce "non-array trivial standard-layout", related to LWG-3034.
strings\string.view\char.bad.fail.cpp
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ tests\P0896R4_ranges_alg_find_if
tests\P0896R4_ranges_alg_find_if_not
tests\P0896R4_ranges_alg_for_each
tests\P0896R4_ranges_alg_for_each_n
tests\P0896R4_ranges_alg_is_permutation
tests\P0896R4_ranges_alg_mismatch
tests\P0896R4_ranges_alg_move
tests\P0896R4_ranges_alg_none_of
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_is_permutation/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_matrix.lst
Loading