[libcxx-commits] [libcxx] [libc++] Fix several double-moves in the code base (PR #104616)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Aug 16 10:08:09 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

<details>
<summary>Changes</summary>

This patch hardens the "test iterators" we use to test algorithms by ensuring that they don't get double-moved. As a result of this hardening, the tests started reporting multiple failures where we would double-move iterators, which are being fixed in this patch.

In particular:
- Fixed a double-move in pstl.partition
- Add coverage for begin()/end() in subrange tests
- Fix tests for ranges::ends_with and ranges::contains, which were incorrectly calling begin() twice on the same subrange containing non-copyable input iterators.

Fixes #<!-- -->100709

---

Patch is 33.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104616.diff


8 Files Affected:

- (modified) libcxx/include/__algorithm/partition.h (+1-1) 
- (modified) libcxx/include/__pstl/backends/default.h (+1-1) 
- (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp (+2) 
- (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains.pass.cpp (+22-16) 
- (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp (+144-116) 
- (added) libcxx/test/std/ranges/range.utility/range.subrange/begin_end.pass.cpp (+54) 
- (added) libcxx/test/support/double_move_tracker.h (+43) 
- (modified) libcxx/test/support/test_iterators.h (+47-16) 


``````````diff
diff --git a/libcxx/include/__algorithm/partition.h b/libcxx/include/__algorithm/partition.h
index 824e49b9ec2149..bd0dccfaf92abe 100644
--- a/libcxx/include/__algorithm/partition.h
+++ b/libcxx/include/__algorithm/partition.h
@@ -29,7 +29,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _Forw
 __partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag) {
   while (true) {
     if (__first == __last)
-      return std::make_pair(std::move(__first), std::move(__first));
+      return std::make_pair(__first, __first);
     if (!__pred(*__first))
       break;
     ++__first;
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 61a128805f8549..b655da51fe340b 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -163,7 +163,7 @@ struct __is_partitioned<__default_backend_tag, _ExecutionPolicy> {
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
   operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept {
     using _FindIfNot   = __dispatch<__find_if_not, __current_configuration, _ExecutionPolicy>;
-    auto __maybe_first = _FindIfNot()(__policy, std::move(__first), std::move(__last), __pred);
+    auto __maybe_first = _FindIfNot()(__policy, std::move(__first), __last, __pred);
     if (__maybe_first == nullopt)
       return nullopt;
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp
index 3eaeaa432c490f..87beba183a2842 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp
@@ -98,11 +98,13 @@ test()
 
 int main(int, char**)
 {
+    test<forward_iterator<int*> >();
     test<bidirectional_iterator<int*> >();
     test<random_access_iterator<int*> >();
     test<int*>();
 
 #if TEST_STD_VER >= 20
+    static_assert(test<forward_iterator<int*>>());
     static_assert(test<bidirectional_iterator<int*>>());
     static_assert(test<random_access_iterator<int*>>());
     static_assert(test<int*>());
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains.pass.cpp
index f710ca2c319dd6..5326985b3527e7 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains.pass.cpp
@@ -65,12 +65,13 @@ constexpr void test_iterators() {
   using ValueT = std::iter_value_t<Iter>;
   { // simple tests
     ValueT a[] = {1, 2, 3, 4, 5, 6};
-    auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
     {
+      auto whole                            = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
       std::same_as<bool> decltype(auto) ret = std::ranges::contains(whole.begin(), whole.end(), 3);
       assert(ret);
     }
     {
+      auto whole                            = std::ranges::subrange(Iter(a), Sent(Iter(a + 6)));
       std::same_as<bool> decltype(auto) ret = std::ranges::contains(whole, 3);
       assert(ret);
     }
@@ -78,65 +79,70 @@ constexpr void test_iterators() {
 
   { // check that a range with a single element works
     ValueT a[] = {32};
-    auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 1)));
     {
-      bool ret = std::ranges::contains(whole.begin(), whole.end(), 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 1)));
+      bool ret   = std::ranges::contains(whole.begin(), whole.end(), 32);
       assert(ret);
     }
     {
-      bool ret = std::ranges::contains(whole, 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 1)));
+      bool ret   = std::ranges::contains(whole, 32);
       assert(ret);
     }
   }
 
   { // check that an empty range works
     std::array<ValueT, 0> a = {};
-    auto whole              = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
     {
-      bool ret = std::ranges::contains(whole.begin(), whole.end(), 1);
+      auto whole = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
+      bool ret   = std::ranges::contains(whole.begin(), whole.end(), 1);
       assert(!ret);
     }
     {
-      bool ret = std::ranges::contains(whole, 1);
+      auto whole = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
+      bool ret   = std::ranges::contains(whole, 1);
       assert(!ret);
     }
   }
 
   { // check that the first element matches
     ValueT a[] = {32, 3, 2, 1, 0, 23, 21, 9, 40, 100};
-    auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 10)));
     {
-      bool ret = std::ranges::contains(whole.begin(), whole.end(), 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 10)));
+      bool ret   = std::ranges::contains(whole.begin(), whole.end(), 32);
       assert(ret);
     }
     {
-      bool ret = std::ranges::contains(whole, 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 10)));
+      bool ret   = std::ranges::contains(whole, 32);
       assert(ret);
     }
   }
 
   { // check that the last element matches
     ValueT a[] = {3, 22, 1, 43, 99, 0, 56, 100, 32};
-    auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 9)));
     {
-      bool ret = std::ranges::contains(whole.begin(), whole.end(), 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 9)));
+      bool ret   = std::ranges::contains(whole.begin(), whole.end(), 32);
       assert(ret);
     }
     {
-      bool ret = std::ranges::contains(whole, 32);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 9)));
+      bool ret   = std::ranges::contains(whole, 32);
       assert(ret);
     }
   }
 
   { // no match
     ValueT a[] = {13, 1, 21, 4, 5};
-    auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 5)));
     {
-      bool ret = std::ranges::contains(whole.begin(), whole.end(), 10);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 5)));
+      bool ret   = std::ranges::contains(whole.begin(), whole.end(), 10);
       assert(!ret);
     }
     {
-      bool ret = std::ranges::contains(whole, 10);
+      auto whole = std::ranges::subrange(Iter(a), Sent(Iter(a + 5)));
+      bool ret   = std::ranges::contains(whole, 10);
       assert(!ret);
     }
   }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
index 685bd692422ac8..199e6a786e5ba3 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
@@ -49,7 +49,8 @@ static_assert(!HasEndsWithIt<int*, int*, int*, SentinelForNotWeaklyEqualityCompa
 
 template <class Range1, class Range2 = UncheckedRange<int*>>
 concept HasEndsWithR = requires(Range1&& range1, Range2&& range2) {
-    std::ranges::ends_with(std::forward<Range1>(range1), std::forward<Range2>(range2)); };
+  std::ranges::ends_with(std::forward<Range1>(range1), std::forward<Range2>(range2));
+};
 
 static_assert(HasEndsWithR<UncheckedRange<int*>>);
 static_assert(!HasEndsWithR<ForwardRangeNotDerivedFrom>);
@@ -61,19 +62,21 @@ static_assert(!HasEndsWithR<UncheckedRange<int*>, UncheckedRange<int**>>); // no
 static_assert(!HasEndsWithR<UncheckedRange<int*>, ForwardRangeNotDerivedFrom>);
 static_assert(!HasEndsWithR<UncheckedRange<int*>, ForwardRangeNotSentinelSemiregular>);
 
-// clang-format off
 template <class Iter1, class Sent1 = Iter1, class Iter2, class Sent2 = Iter2>
 constexpr void test_iterators() {
   { // simple tests
-    int a[]          = {1, 2, 3, 4, 5, 6};
-    int p[]          = {4, 5, 6};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
+    int a[] = {1, 2, 3, 4, 5, 6};
+    int p[] = {4, 5, 6};
     {
-      [[maybe_unused]] std::same_as<bool> decltype(auto) ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
+      [[maybe_unused]] std::same_as<bool> decltype(auto) ret =
+          std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(ret);
     }
     {
+      auto whole                                             = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix                                            = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
       [[maybe_unused]] std::same_as<bool> decltype(auto) ret = std::ranges::ends_with(whole, suffix);
       assert(ret);
     }
@@ -82,14 +85,16 @@ constexpr void test_iterators() {
   { // suffix doesn't match
     int a[] = {1, 2, 3, 4, 5, 6};
     int p[] = {1, 2, 3};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
     {
-      bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(!ret);
     }
     {
-      bool ret = std::ranges::ends_with(whole, suffix);
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
       assert(!ret);
     }
   }
@@ -97,14 +102,16 @@ constexpr void test_iterators() {
   { // range consists of just one element
     int a[] = {1};
     int p[] = {1};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 1)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
     {
-      bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 1)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(ret);
     }
     {
-      bool ret = std::ranges::ends_with(whole, suffix);
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 1)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
       assert(ret);
     }
   }
@@ -112,14 +119,16 @@ constexpr void test_iterators() {
   { // suffix consists of just one element
     int a[] = {5, 1, 2, 4, 3};
     int p[] = {3};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
     {
-      bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(ret);
     }
     {
-      bool ret = std::ranges::ends_with(whole, suffix);
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
       assert(ret);
     }
   }
@@ -127,14 +136,16 @@ constexpr void test_iterators() {
   { // range and suffix are identical
     int a[] = {1, 2, 3, 4, 5, 6};
     int p[] = {1, 2, 3, 4, 5, 6};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 6)));
     {
-      bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 6)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(ret);
     }
     {
-      bool ret = std::ranges::ends_with(whole, suffix);
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 6)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
       assert(ret);
     }
   }
@@ -142,111 +153,128 @@ constexpr void test_iterators() {
   { // suffix is longer than range
     int a[] = {3, 4, 5, 6, 7, 8};
     int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
-    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
     {
-      bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
       assert(!ret);
     }
     {
-      bool ret = std::ranges::ends_with(whole, suffix);
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
       assert(!ret);
     }
- }
+  }
 
- { // suffix has zero length
-   int a[] = {1, 2, 3, 4, 5, 6};
-   std::array<int, 0> p = {};
-   auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-   auto suffix  = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
-     assert(ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix);
-     assert(ret);
-   }
- }
+  { // suffix has zero length
+    int a[]              = {1, 2, 3, 4, 5, 6};
+    std::array<int, 0> p = {};
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      assert(ret);
+    }
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
+      bool ret    = std::ranges::ends_with(whole, suffix);
+      assert(ret);
+    }
+  }
 
- { // range has zero length
-   std::array<int, 0> a = {};
-   int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
-   auto whole = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
-   auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
-     assert(!ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix);
-     assert(!ret);
-   }
- }
+  { // range has zero length
+    std::array<int, 0> a = {};
+    int p[]              = {1, 2, 3, 4, 5, 6, 7, 8};
+    {
+      auto whole  = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      assert(!ret);
+    }
+    {
+      auto whole  = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
+      assert(!ret);
+    }
+  }
 
- { // subarray
-   int a[] = {0, 3, 5, 10, 7, 3, 5, 89, 3, 5, 2, 1, 8, 6};
-   int p[] = {3, 5};
-   auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 13)));
-   auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
-     assert(!ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix);
-     assert(!ret);
-   }
- }
+  { // subarray
+    int a[] = {0, 3, 5, 10, 7, 3, 5, 89, 3, 5, 2, 1, 8, 6};
+    int p[] = {3, 5};
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 13)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      assert(!ret);
+    }
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 13)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
+      assert(!ret);
+    }
+  }
 
- { // repeated suffix
-   int a[] = {8, 6, 3, 5, 1, 2};
-   int p[] = {1, 2, 1, 2};
-   auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-   auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
-     assert(!ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix);
-     assert(!ret);
-   }
- }
+  { // repeated suffix
+    int a[] = {8, 6, 3, 5, 1, 2};
+    int p[] = {1, 2, 1, 2};
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
+      assert(!ret);
+    }
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
+      bool ret    = std::ranges::ends_with(whole, suffix);
+      assert(!ret);
+    }
+  }
 
- { // check that the predicate is used
-   int a[] = {5, 1, 3, 2, 7};
-   int p[] = {-2, -7};
-   auto pred = [](int l, int r) { return l * -1 == r; };
-   auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
-   auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end(), pred);
-     assert(ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix, pred);
-     assert(ret);
-   }
- }
+  { // check that the predicate is used
+    int a[]   = {5, 1, 3, 2, 7};
+    int p[]   = {-2, -7};
+    auto pred = [](int l, int r) { return l * -1 == r; };
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
+      bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end(), pred);
+      assert(ret);
+    }
+    {
+      auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
+      auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
+      bool ret    = std::ranges::ends_with(whole, suffix, pred);
+      assert(ret);
+    }
+  }
 
- { // check that the projections are used
-   int a[] = {1, 3, 15, 1, 2, 1};
-   int p[] = {2, 1, 2};
-   auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
-   auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
-   {
-     bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end(), {},
-         [](int i) { return i - 3; },
-         [](int i) { return i * -1; });
-     assert(ret);
-   }
-   {
-     bool ret = std::ranges::ends_with(whole, suffix, {},
-         [](int i) { return i - 3; },
-         [](int i) { return i * -1; });
-     assert(ret);
-   }
+  { // check that the projections are ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/104616


More information about the libcxx-commits mailing list