[libcxx-commits] [libcxx] 1bbf3a3 - [libc++] Fix `reverse_iterator` when underlying is c++20 `bidirectional_iterator` but not `Cpp17BidirectionalIterator` (#112100)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Oct 19 03:09:28 PDT 2024


Author: Hui
Date: 2024-10-19T11:09:25+01:00
New Revision: 1bbf3a37056761ec407031431e28f856428566f0

URL: https://github.com/llvm/llvm-project/commit/1bbf3a37056761ec407031431e28f856428566f0
DIFF: https://github.com/llvm/llvm-project/commit/1bbf3a37056761ec407031431e28f856428566f0.diff

LOG: [libc++] Fix `reverse_iterator` when underlying is c++20 `bidirectional_iterator` but not `Cpp17BidirectionalIterator` (#112100)

`reverse_iterator` supports either c++20 `bidirectional_iterator` or
`Cpp17BidirectionalIterator `
http://eel.is/c++draft/reverse.iter.requirements

The current `reverse_iterator` uses `std::prev` in its `operator->`,
which only supports the `Cpp17BidirectionalIterator` properly.

If the underlying iterator is c++20 `bidirectional_iterator` but does
not satisfy the named requirement `Cpp17BidirectionalIterator`,
(examples are `zip_view::iterator`, `flat_map::iterator`), the current
`std::prev` silently compiles but does a no-op and returns the same
iterator back. So `reverse_iterator::operator->` will silently give a
wrong answer.

Even if we fix the behaviour of `std::prev`, at best, we could fail to
compile the code. But this is not ok, because we need to support this
kind of iterators in `reverse_iterator`.

The solution is simply to not use `std::prev`.

---------

Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>

Added: 
    

Modified: 
    libcxx/include/__iterator/reverse_iterator.h
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h
index 50c0f21eaa286b..5e88d86ad5e9b2 100644
--- a/libcxx/include/__iterator/reverse_iterator.h
+++ b/libcxx/include/__iterator/reverse_iterator.h
@@ -136,10 +136,12 @@ class _LIBCPP_TEMPLATE_VIS reverse_iterator
   _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const
     requires is_pointer_v<_Iter> || requires(const _Iter __i) { __i.operator->(); }
   {
+    _Iter __tmp = current;
+    --__tmp;
     if constexpr (is_pointer_v<_Iter>) {
-      return std::prev(current);
+      return __tmp;
     } else {
-      return std::prev(current).operator->();
+      return __tmp.operator->();
     }
   }
 #else

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp
index fcf8d88fcf62be..6fe575ebdd9a0d 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp
@@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1), false);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), true);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), false);
+#endif
     test(s, s, true);
     test(s, s+1, false);
     return true;

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp
index fdcd02abb0d8ed..b2bfdb56d646ed 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp
@@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true);
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), false);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), true);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), true);
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s), false);
+#endif
     test(s, s, true);
     test(s, s+1, true);
     test(s+1, s, false);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp
index dce331e519646f..38f9258de31f5e 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp
@@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true);
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), false);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), false);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), true);
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s), false);
+#endif
     test(s, s, false);
     test(s, s+1, true);
     test(s+1, s, false);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp
index e9cea6250a7645..a57930b111314d 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp
@@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false);
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), true);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), true);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), false);
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s), true);
+#endif
     test(s, s, true);
     test(s, s+1, false);
     test(s+1, s, true);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp
index b66147cf3a03c3..4cd3f249d033e1 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp
@@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false);
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), true);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), false);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), false);
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s), true);
+#endif
     test(s, s, false);
     test(s, s+1, false);
     test(s+1, s, true);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp
index 37a6ff1302ce77..509ac297c3cba6 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp
@@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1), true);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false);
     test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true);
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s), false);
+    test(cpp20_random_access_iterator<const char*>(s), cpp20_random_access_iterator<const char*>(s + 1), true);
+#endif
     test(s, s, false);
     test(s, s+1, true);
     return true;

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp
index 0e5123a49e2b56..f9d2efa7c2a8cc 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp
@@ -59,6 +59,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     Derived d;
     test<bidirectional_iterator<Base*> >(bidirectional_iterator<Derived*>(&d));
     test<random_access_iterator<const Base*> >(random_access_iterator<Derived*>(&d));
+#if TEST_STD_VER >= 20
+    test<cpp20_random_access_iterator<const Base*> >(cpp20_random_access_iterator<Derived*>(&d));
+#endif
     test<Base*>(&d);
 
     char c = '\0';

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp
index fcb96de91d1a02..90047b19f5a63a 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp
@@ -26,6 +26,9 @@ TEST_CONSTEXPR_CXX17 void test() {
 TEST_CONSTEXPR_CXX17 bool tests() {
     test<bidirectional_iterator<const char*> >();
     test<random_access_iterator<char*> >();
+#if TEST_STD_VER >= 20
+    test<cpp20_random_access_iterator<char*> >();
+#endif
     test<char*>();
     test<const char*>();
     return true;

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp
index 801b2cf879ce5b..72e77b08564219 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp
@@ -28,6 +28,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char s[] = "123";
     test(bidirectional_iterator<const char*>(s));
     test(random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp
index 8f315e83f6d7b4..fa967b45b1d9f8 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp
@@ -33,6 +33,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     Derived d;
     test<bidirectional_iterator<Base*> >(bidirectional_iterator<Derived*>(&d));
     test<random_access_iterator<const Base*> >(random_access_iterator<Derived*>(&d));
+#if TEST_STD_VER >= 20
+    test<cpp20_random_access_iterator<const Base*> >(cpp20_random_access_iterator<Derived*>(&d));
+#endif
     test<Base*>(&d);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp
index 4fb33f54260457..35ed17583c8555 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp
@@ -18,20 +18,28 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-TEST_CONSTEXPR_CXX17 bool test() {
-    typedef bidirectional_iterator<int*> Iter;
-    int i = 0;
-    Iter iter(&i);
-    std::reverse_iterator<Iter> const reverse(iter);
-    std::reverse_iterator<Iter>::iterator_type base = reverse.base();
-    assert(base == Iter(&i));
-    return true;
+template <class Iter>
+TEST_CONSTEXPR_CXX17 void test() {
+  int i = 0;
+  Iter iter(&i);
+  std::reverse_iterator<Iter> const reverse(iter);
+  typename std::reverse_iterator<Iter>::iterator_type base = reverse.base();
+  assert(base == Iter(&i));
+}
+
+TEST_CONSTEXPR_CXX17 bool tests() {
+  test<bidirectional_iterator<int*> >();
+  test<random_access_iterator<int*> >();
+#if TEST_STD_VER >= 20
+  test<cpp20_random_access_iterator<int*>>();
+#endif
+  return true;
 }
 
 int main(int, char**) {
-    test();
+  tests();
 #if TEST_STD_VER > 14
-    static_assert(test(), "");
+  static_assert(tests(), "");
 #endif
-    return 0;
+  return 0;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp
index 15d18d9145ef0c..665a1a89223bc4 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp
@@ -24,6 +24,55 @@
 
 #include "test_macros.h"
 
+#if TEST_STD_VER >= 20
+// C++20 bidirectional_iterator that does not satisfy the Cpp17BidirectionalIterator named requirement.
+template <class It>
+class cpp20_bidirectional_iterator_with_arrow {
+  It it_;
+
+public:
+  using iterator_category = std::input_iterator_tag;
+  using iterator_concept  = std::bidirectional_iterator_tag;
+  using value_type        = std::iterator_traits<It>::value_type;
+  using 
diff erence_type   = std::iterator_traits<It>::
diff erence_type;
+
+  cpp20_bidirectional_iterator_with_arrow() : it_() {}
+  explicit cpp20_bidirectional_iterator_with_arrow(It it) : it_(it) {}
+
+  decltype(auto) operator*() const { return *it_; }
+
+  auto operator->() const {
+    if constexpr (std::is_pointer_v<It>) {
+      return it_;
+    } else {
+      return it_.operator->();
+    }
+  }
+
+  cpp20_bidirectional_iterator_with_arrow& operator++() {
+    ++it_;
+    return *this;
+  }
+  cpp20_bidirectional_iterator_with_arrow& operator--() {
+    --it_;
+    return *this;
+  }
+  cpp20_bidirectional_iterator_with_arrow operator++(int) { return cpp20_bidirectional_iterator_with_arrow(it_++); }
+  cpp20_bidirectional_iterator_with_arrow operator--(int) { return cpp20_bidirectional_iterator_with_arrow(it_--); }
+
+  friend bool
+  operator==(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) {
+    return x.it_ == y.it_;
+  }
+  friend bool
+  operator!=(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) {
+    return x.it_ != y.it_;
+  }
+
+  friend It base(const cpp20_bidirectional_iterator_with_arrow& i) { return i.it_; }
+};
+#endif
+
 class A
 {
     int data_;
@@ -113,6 +162,16 @@ int main(int, char**)
 
     static_assert(it1->get() == gC.get(), "");
   }
+#endif
+#if TEST_STD_VER >= 20
+  {
+    // The underlying iterator models c++20 bidirectional_iterator,
+    // but does not satisfy c++17 BidirectionalIterator named requirement
+    B data[] = {1, 2, 3};
+    cpp20_bidirectional_iterator_with_arrow<B*> iter(data + 3);
+    auto ri = std::make_reverse_iterator(iter);
+    assert(ri->get() == 3);
+  }
 #endif
   {
     ((void)gC);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp
index 37a857ceefa83d..8b45bfa09b4fe7 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp
@@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "1234567890";
     test(random_access_iterator<const char*>(s+5), 4, '1');
     test(random_access_iterator<const char*>(s+5), 0, '5');
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 4, '1');
+    test(cpp20_random_access_iterator<const char*>(s + 5), 0, '5');
+#endif
     test(s+5, 4, '1');
     test(s+5, 0, '5');
     return true;

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp
index 292c6da9a7733e..c3a489085c68b0 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp
@@ -21,6 +21,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_iterators.h"
 
 class A
 {
@@ -47,6 +48,10 @@ int main(int, char**)
 {
     A a;
     test(&a+1, A());
+    test(random_access_iterator<A*>(&a + 1), A());
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<A*>(&a + 1), A());
+#endif
 
 #if TEST_STD_VER > 14
     {

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp
index 8c83ec1e9389f9..91c2d9363619bf 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp
@@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::
diff eren
 TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "1234567890";
     test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 5, cpp20_random_access_iterator<const char*>(s + 10));
+#endif
     test(s+5, 5, s+10);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp
index e32fac9fc24fe1..2a2746f2cc52bd 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp
@@ -29,7 +29,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::
diff eren
 
 TEST_CONSTEXPR_CXX17 bool tests() {
     char const* s = "1234567890";
-    test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s));
+    test(random_access_iterator<const char*>(s + 5), 5, random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 5, cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s+5, 5, s);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp
index f2474dd7669f2c..759cacad94e24c 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp
@@ -28,7 +28,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::
diff eren
 
 TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "1234567890";
-    test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10));
+    test(random_access_iterator<const char*>(s + 5), 5, random_access_iterator<const char*>(s + 10));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 5, cpp20_random_access_iterator<const char*>(s + 10));
+#endif
     test(s+5, 5, s+10);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp
index 5673425e796757..24fa84e4f37c8b 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp
@@ -28,7 +28,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::
diff eren
 
 TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "1234567890";
-    test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s));
+    test(random_access_iterator<const char*>(s + 5), 5, random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 5, cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s+5, 5, s);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp
index 24bedad314b7e8..f0551b5efece09 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp
@@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "123";
     test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s+2));
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s+2));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s + 2));
+#endif
     test(s+1, s+2);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp
index e15bfb2fd15096..f1d3ea21a5b860 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp
@@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "123";
     test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s));
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s+1, s);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp
index 2fbd530a085dcc..5a2ac785703672 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp
@@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "123";
     test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s+2));
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s+2));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s + 2));
+#endif
     test(s+1, s+2);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp
index 5efc8a39e22aa8..6087eedd2449f2 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp
@@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "123";
     test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s));
     test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 1), cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s+1, s);
     return true;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp
index 401eecb2a3b838..4a4e474a550835 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp
@@ -22,24 +22,34 @@
 #include "test_iterators.h"
 
 template <class It>
-TEST_CONSTEXPR_CXX17 void test(It i) {
-    const std::reverse_iterator<It> r = std::make_reverse_iterator(i);
-    assert(r.base() == i);
+TEST_CONSTEXPR_CXX17 void test_one(It i) {
+  const std::reverse_iterator<It> r = std::make_reverse_iterator(i);
+  assert(r.base() == i);
+}
+
+template <class It>
+TEST_CONSTEXPR_CXX17 void test() {
+  const char* s = "1234567890";
+  It b(s);
+  It e(s + 10);
+  while (b != e)
+    test_one(b++);
 }
 
 TEST_CONSTEXPR_CXX17 bool tests() {
-    const char* s = "1234567890";
-    random_access_iterator<const char*> b(s);
-    random_access_iterator<const char*> e(s+10);
-    while (b != e)
-        test (b++);
-    return true;
+  test<const char*>();
+  test<bidirectional_iterator<const char*>>();
+  test<random_access_iterator<const char*>>();
+#if TEST_STD_VER >= 20
+  test<cpp20_random_access_iterator<const char*>>();
+#endif
+  return true;
 }
 
 int main(int, char**) {
-    tests();
+  tests();
 #if TEST_STD_VER > 14
-    static_assert(tests(), "");
+  static_assert(tests(), "");
 #endif
-    return 0;
+  return 0;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp
index f7f74d145d73c6..676f6e1b491695 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp
@@ -23,45 +23,63 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-template <class, class, class = void> struct HasMinus : std::false_type {};
-template <class R1, class R2> struct HasMinus<R1, R2, decltype((R1() - R2(), void()))> : std::true_type {};
+template <class, class, class = void>
+struct HasMinus : std::false_type {};
+template <class R1, class R2>
+struct HasMinus<R1, R2, decltype((R1() - R2(), void()))> : std::true_type {};
+
+// Test non-subtractable base iterator types
+static_assert(HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<int*> >::value, "");
+static_assert(HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<const int*> >::value, "");
+
+#if TEST_STD_VER >= 11
+static_assert(!HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<char*> >::value, "");
+static_assert(!HasMinus<std::reverse_iterator<bidirectional_iterator<int*> >,
+                        std::reverse_iterator<bidirectional_iterator<int*> > >::value,
+              "");
+#endif
 
 template <class It1, class It2>
-TEST_CONSTEXPR_CXX17 void test(It1 l, It2 r, std::ptr
diff _t x) {
-    const std::reverse_iterator<It1> r1(l);
-    const std::reverse_iterator<It2> r2(r);
-    assert((r1 - r2) == x);
+TEST_CONSTEXPR_CXX17 void test_one(It1 l, It2 r, std::ptr
diff _t x) {
+  const std::reverse_iterator<It1> r1(l);
+  const std::reverse_iterator<It2> r2(r);
+  assert((r1 - r2) == x);
 }
 
-TEST_CONSTEXPR_CXX17 bool tests() {
-    using PC = const char*;
-    char s[3] = {0};
-
-    // Test same base iterator type
-    test(s, s, 0);
-    test(s, s+1, 1);
-    test(s+1, s, -1);
+template <class Iter>
+TEST_CONSTEXPR_CXX17 void test() {
+  // Test same base iterator type
+  char s[3] = {0};
 
-    // Test 
diff erent (but subtractable) base iterator types
-    test(PC(s), s, 0);
-    test(PC(s), s+1, 1);
-    test(PC(s+1), s, -1);
+  test_one(Iter(s), Iter(s), 0);
+  test_one(Iter(s), Iter(s + 1), 1);
+  test_one(Iter(s + 1), Iter(s), -1);
+}
 
-    // Test non-subtractable base iterator types
-    static_assert( HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<int*> >::value, "");
-    static_assert( HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<const int*> >::value, "");
-#if TEST_STD_VER >= 11
-    static_assert(!HasMinus<std::reverse_iterator<int*>, std::reverse_iterator<char*> >::value, "");
-    static_assert(!HasMinus<std::reverse_iterator<bidirectional_iterator<int*> >, std::reverse_iterator<bidirectional_iterator<int*> > >::value, "");
+TEST_CONSTEXPR_CXX17 bool tests() {
+  {
+    test<char*>();
+    test<random_access_iterator<char*> >();
+#if TEST_STD_VER >= 20
+    test<cpp20_random_access_iterator<char*>>();
 #endif
+  }
+  {
+    // Test 
diff erent (but subtractable) base iterator types
+    using PC  = const char*;
+    char s[3] = {0};
+    test_one(PC(s), s, 0);
+    test_one(PC(s), s + 1, 1);
+    test_one(PC(s + 1), s, -1);
+  }
 
-    return true;
+  return true;
 }
 
 int main(int, char**) {
-    tests();
+  tests();
 #if TEST_STD_VER > 14
-    static_assert(tests(), "");
+  static_assert(tests(), "");
 #endif
-    return 0;
+  return 0;
 }

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp
index aeb9f89dd48725..9ead123781bc86 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp
@@ -29,6 +29,9 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::
diff eren
 TEST_CONSTEXPR_CXX17 bool tests() {
     const char* s = "1234567890";
     test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s));
+#if TEST_STD_VER >= 20
+    test(cpp20_random_access_iterator<const char*>(s + 5), 5, cpp20_random_access_iterator<const char*>(s));
+#endif
     test(s+5, 5, s);
     return true;
 }


        


More information about the libcxx-commits mailing list