[libcxx-commits] [libcxx] 0473318 - [libcxx][iterator] adds `std::indirectly_readable` and `std::indirectly_writable`

Christopher Di Bella via libcxx-commits libcxx-commits at lists.llvm.org
Wed Apr 21 10:15:07 PDT 2021


Author: Christopher Di Bella
Date: 2021-04-21T17:14:28Z
New Revision: 04733181b5136e2b3df2b37c6bdd9e25f8afecd0

URL: https://github.com/llvm/llvm-project/commit/04733181b5136e2b3df2b37c6bdd9e25f8afecd0
DIFF: https://github.com/llvm/llvm-project/commit/04733181b5136e2b3df2b37c6bdd9e25f8afecd0.diff

LOG: [libcxx][iterator] adds `std::indirectly_readable` and `std::indirectly_writable`

Implements parts of:
    * P0896R4 The One Ranges Proposal`

Depends on D99873.

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D100073

Added: 
    libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
    libcxx/test/support/read_write.h

Modified: 
    libcxx/include/__iterator/concepts.h
    libcxx/include/__iterator/incrementable_traits.h
    libcxx/include/__iterator/iter_move.h
    libcxx/include/__iterator/iterator_traits.h
    libcxx/include/__iterator/readable_traits.h
    libcxx/include/iterator

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index c02944f1a1f1..c7b59ca95982 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -12,6 +12,10 @@
 
 #include <__config>
 #include <concepts>
+#include <__iterator/iter_move.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/readable_traits.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
@@ -24,18 +28,36 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if !defined(_LIBCPP_HAS_NO_RANGES)
 
-template<class _Tp>
-using __with_reference = _Tp&;
+// clang-format off
 
-template<class _Tp>
-concept __referenceable = requires {
-  typename __with_reference<_Tp>;
-};
+// [iterator.concept.readable]
+template<class _In>
+concept __indirectly_readable_impl =
+  requires(const _In __in) {
+    typename iter_value_t<_In>;
+    typename iter_reference_t<_In>;
+    typename iter_rvalue_reference_t<_In>;
+    { *__in } -> same_as<iter_reference_t<_In> >;
+    { ranges::iter_move(__in) } -> same_as<iter_rvalue_reference_t<_In> >;
+  } &&
+  common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> &&
+  common_reference_with<iter_reference_t<_In>&&, iter_rvalue_reference_t<_In>&&> &&
+  common_reference_with<iter_rvalue_reference_t<_In>&&, const iter_value_t<_In>&>;
 
-template<class _Tp>
-concept __dereferenceable = requires(_Tp& __t) {
-  { *__t } -> __referenceable; // not required to be equality-preserving
-};
+template<class _In>
+concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In> >;
+
+// [iterator.concept.writable]
+template<class _Out, class _Tp>
+concept indirectly_writable =
+  requires(_Out&& __o, _Tp&& __t) {
+    *__o = _VSTD::forward<_Tp>(__t);                        // not required to be equality-preserving
+    *_VSTD::forward<_Out>(__o) = _VSTD::forward<_Tp>(__t);  // not required to be equality-preserving
+    const_cast<const iter_reference_t<_Out>&&>(*__o) = _VSTD::forward<_Tp>(__t);                       // not required to be equality-preserving
+    const_cast<const iter_reference_t<_Out>&&>(*_VSTD::forward<_Out>(__o)) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving
+  };
+
+// clang-format on
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 

diff  --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h
index 2acabbaa1a9b..28717e06a142 100644
--- a/libcxx/include/__iterator/incrementable_traits.h
+++ b/libcxx/include/__iterator/incrementable_traits.h
@@ -11,7 +11,7 @@
 #define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H
 
 #include <__config>
-#include <__iterator/concepts.h>
+#include <concepts>
 #include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)

diff  --git a/libcxx/include/__iterator/iter_move.h b/libcxx/include/__iterator/iter_move.h
index 02cdf56724df..c83eb77218da 100644
--- a/libcxx/include/__iterator/iter_move.h
+++ b/libcxx/include/__iterator/iter_move.h
@@ -11,7 +11,7 @@
 #define _LIBCPP___ITERATOR_ITER_MOVE_H
 
 #include <__config>
-#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
 #include <concepts> // __class_or_enum
 #include <type_traits>
 #include <utility>

diff  --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h
index eee6f6c37b2f..b80439f7d3e9 100644
--- a/libcxx/include/__iterator/iterator_traits.h
+++ b/libcxx/include/__iterator/iterator_traits.h
@@ -27,9 +27,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if !defined(_LIBCPP_HAS_NO_RANGES)
 
+template <class _Tp>
+using __with_reference = _Tp&;
+
+template <class _Tp>
+concept __referenceable = requires {
+  typename __with_reference<_Tp>;
+};
+
+template <class _Tp>
+concept __dereferenceable = requires(_Tp& __t) {
+  { *__t } -> __referenceable; // not required to be equality-preserving
+};
+
 // [iterator.traits]
 template<__dereferenceable _Tp>
 using iter_reference_t = decltype(*declval<_Tp&>());
+
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 
 template <class _Iter>

diff  --git a/libcxx/include/__iterator/readable_traits.h b/libcxx/include/__iterator/readable_traits.h
index 8566f869cc14..9761756b4c1a 100644
--- a/libcxx/include/__iterator/readable_traits.h
+++ b/libcxx/include/__iterator/readable_traits.h
@@ -11,7 +11,8 @@
 #define _LIBCPP___ITERATOR_READABLE_TRAITS_H
 
 #include <__config>
-#include <__iterator/concepts.h>
+#include <concepts>
+#include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header

diff  --git a/libcxx/include/iterator b/libcxx/include/iterator
index 34244358d75c..33b477a59dba 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -43,6 +43,15 @@ template<dereferenceable T>
   requires ...
 using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<T&>())); // since C++20
 
+// [iterator.concepts], iterator concepts
+// [iterator.concept.readable], concept indirectly_­readable
+template<class In>
+  concept indirectly_readable = see below;                // since C++20
+
+// [iterator.concept.writable], concept indirectly_­writable
+template<class Out, class T>
+  concept indirectly_writable = see below;                // since C++20
+
 template<class Category, class T, class Distance = ptr
diff _t,
          class Pointer = T*, class Reference = T&>
 struct iterator

diff  --git a/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..914ce0828627
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <map>
+
+#include <iterator>
+
+using iterator = std::map<int, int>::iterator;
+using const_iterator = std::map<int, int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..2d7bdcf8be3b
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <map>
+
+#include <iterator>
+
+using iterator = std::multimap<int, int>::iterator;
+using const_iterator = std::multimap<int, int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..2d493c18716f
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <set>
+
+#include <iterator>
+
+using iterator = std::multiset<int>::iterator;
+using const_iterator = std::multiset<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..5cf798945f39
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <set>
+
+#include <iterator>
+
+using iterator = std::set<int>::iterator;
+using const_iterator = std::set<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..21a98a51b625
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <array>
+
+#include <iterator>
+
+using iterator = std::array<int, 10>::iterator;
+using const_iterator = std::array<int, 10>::const_iterator;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, int>);

diff  --git a/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..f159576d6837
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/deque/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <deque>
+
+#include <iterator>
+
+using iterator = std::deque<int>::iterator;
+using const_iterator = std::deque<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..b6f3096680b8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.iter/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator
+
+#include <forward_list>
+
+#include <iterator>
+
+using iterator = std::forward_list<int>::iterator;
+using const_iterator = std::forward_list<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..00df594ea6d7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/list/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <list>
+
+#include <iterator>
+
+using iterator = std::list<int>::iterator;
+using const_iterator = std::list<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..1c84e6616830
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <vector>
+
+#include <iterator>
+
+using iterator = std::vector<bool>::iterator;
+using const_iterator = std::vector<bool>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..25518561c9f5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <vector>
+
+#include <iterator>
+
+using iterator = std::vector<int>::iterator;
+using const_iterator = std::vector<int>::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..5005d269f2b0
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.map/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, local_iterator, const_local_iterator
+
+#include <unordered_map>
+
+#include <iterator>
+
+using iterator = std::unordered_map<int, int>::iterator;
+using const_iterator = std::unordered_map<int, int>::const_iterator;
+using local_iterator = std::unordered_map<int, int>::local_iterator;
+using const_local_iterator = std::unordered_map<int, int>::const_local_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);
+
+static_assert(std::indirectly_readable<local_iterator>);
+static_assert(!std::indirectly_writable<local_iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_local_iterator>);
+static_assert(!std::indirectly_writable<const_local_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..44a6997dd27e
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multimap/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, local_iterator, const_local_iterator
+
+#include <unordered_map>
+
+#include <iterator>
+
+using iterator = std::unordered_multimap<int, int>::iterator;
+using const_iterator = std::unordered_multimap<int, int>::const_iterator;
+using local_iterator = std::unordered_multimap<int, int>::local_iterator;
+using const_local_iterator = std::unordered_multimap<int, int>::const_local_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);
+
+static_assert(std::indirectly_readable<local_iterator>);
+static_assert(!std::indirectly_writable<local_iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_local_iterator>);
+static_assert(!std::indirectly_writable<const_local_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..83d440f90083
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multiset/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, local_iterator, const_local_iterator
+
+#include <unordered_set>
+
+#include <iterator>
+
+using iterator = std::unordered_multiset<int>::iterator;
+using const_iterator = std::unordered_multiset<int>::const_iterator;
+using local_iterator = std::unordered_multiset<int>::local_iterator;
+using const_local_iterator = std::unordered_multiset<int>::const_local_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);
+
+static_assert(std::indirectly_readable<local_iterator>);
+static_assert(!std::indirectly_writable<local_iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_local_iterator>);
+static_assert(!std::indirectly_writable<const_local_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..933d5162481a
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.set/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, local_iterator, const_local_iterator
+
+#include <unordered_set>
+
+#include <iterator>
+
+using iterator = std::unordered_set<int>::iterator;
+using const_iterator = std::unordered_set<int>::const_iterator;
+using local_iterator = std::unordered_set<int>::local_iterator;
+using const_local_iterator = std::unordered_set<int>::const_local_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);
+
+static_assert(std::indirectly_readable<local_iterator>);
+static_assert(!std::indirectly_writable<local_iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_local_iterator>);
+static_assert(!std::indirectly_writable<const_local_iterator, value_type>);

diff  --git a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..769f15f37fd8
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, reverse_iterator
+
+#include <span>
+
+#include <iterator>
+
+using iterator = std::span<int>::iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);

diff  --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..a0c41410c859
--- /dev/null
+++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// directory_iterator, recursive_directory_iterator
+
+#include "filesystem_include.h"
+
+#include <iterator>
+
+static_assert(std::indirectly_readable<fs::directory_iterator>);
+static_assert(!std::indirectly_writable<fs::directory_iterator, fs::directory_iterator::value_type>);
+
+static_assert(std::indirectly_readable<fs::recursive_directory_iterator>);
+static_assert(
+    !std::indirectly_writable<fs::recursive_directory_iterator, fs::recursive_directory_iterator::value_type>);

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp
new file mode 100644
index 000000000000..1734c26878e7
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp
@@ -0,0 +1,199 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In>
+// concept indirectly_readable;
+
+#include <iterator>
+
+#include <concepts>
+
+#include "read_write.h"
+
+template <class In>
+[[nodiscard]] constexpr bool check_indirectly_readable() {
+  constexpr bool result = std::indirectly_readable<In>;
+  static_assert(std::indirectly_readable<In const> == result);
+  static_assert(std::indirectly_readable<In volatile> == result);
+  static_assert(std::indirectly_readable<In const volatile> == result);
+  static_assert(std::indirectly_readable<In const&> == result);
+  static_assert(std::indirectly_readable<In volatile&> == result);
+  static_assert(std::indirectly_readable<In const volatile&> == result);
+  static_assert(std::indirectly_readable<In const&&> == result);
+  static_assert(std::indirectly_readable<In volatile&&> == result);
+  static_assert(std::indirectly_readable<In const volatile&&> == result);
+  return result;
+}
+
+static_assert(!check_indirectly_readable<void*>());
+static_assert(!check_indirectly_readable<void const*>());
+static_assert(!check_indirectly_readable<void volatile*>());
+static_assert(!check_indirectly_readable<void const volatile*>());
+
+static_assert(check_indirectly_readable<int*>());
+static_assert(check_indirectly_readable<int const*>());
+static_assert(check_indirectly_readable<int volatile*>());
+static_assert(check_indirectly_readable<int const volatile*>());
+
+static_assert(check_indirectly_readable<value_type_indirection>());
+static_assert(check_indirectly_readable<element_type_indirection>());
+static_assert(check_indirectly_readable<proxy_indirection>());
+static_assert(check_indirectly_readable<read_only_indirection>());
+
+struct indirection_mismatch {
+  using value_type = int;
+  float& operator*() const;
+};
+static_assert(!std::same_as<std::iter_value_t<indirection_mismatch>, std::iter_reference_t<indirection_mismatch> > &&
+              check_indirectly_readable<indirection_mismatch>());
+static_assert(!check_indirectly_readable<missing_dereference>());
+
+// `iter_rvalue_reference_t` can't be missing unless the dereference operator is also missing.
+
+struct iter_move_mismatch {
+  using value_type = int;
+  value_type& operator*() const;
+
+  friend float& iter_move(iter_move_mismatch&);
+};
+static_assert(!check_indirectly_readable<iter_move_mismatch>());
+
+struct indirection_and_iter_move_mismatch {
+  using value_type = int;
+  float& operator*() const;
+
+  friend unsigned long long& iter_move(indirection_and_iter_move_mismatch&);
+};
+static_assert(!check_indirectly_readable<indirection_and_iter_move_mismatch>());
+
+struct missing_iter_value_t {
+  int operator*() const;
+};
+static_assert(!check_indirectly_readable<missing_iter_value_t>());
+
+struct unrelated_lvalue_ref_and_rvalue_ref {};
+
+struct iter_ref1 {};
+namespace std {
+template <>
+struct common_reference<iter_ref1&, iter_ref1&&> {};
+
+template <>
+struct common_reference<iter_ref1&&, iter_ref1&> {};
+} // namespace std
+static_assert(!std::common_reference_with<iter_ref1&, iter_ref1&&>);
+
+struct bad_iter_reference_t {
+  using value_type = int;
+  iter_ref1& operator*() const;
+};
+static_assert(!check_indirectly_readable<bad_iter_reference_t>());
+
+struct iter_ref2 {};
+struct iter_rvalue_ref {};
+
+struct unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue {
+  using value_type = iter_ref2;
+  iter_ref2& operator*() const;
+  friend iter_rvalue_ref&& iter_move(unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue);
+};
+static_assert(!check_indirectly_readable<unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue>());
+
+struct iter_ref3 {
+  operator iter_rvalue_ref() const;
+};
+namespace std {
+template <template <class> class XQual, template <class> class YQual>
+struct basic_common_reference<iter_ref3, iter_rvalue_ref, XQual, YQual> {
+  using type = iter_rvalue_ref;
+};
+template <template <class> class XQual, template <class> class YQual>
+struct basic_common_reference<iter_rvalue_ref, iter_ref3, XQual, YQual> {
+  using type = iter_rvalue_ref;
+};
+} // namespace std
+static_assert(std::common_reference_with<iter_ref3&&, iter_rvalue_ref&&>);
+
+struct 
diff erent_reference_types_with_common_reference {
+  using value_type = iter_ref3;
+  iter_ref3& operator*() const;
+  friend iter_rvalue_ref&& iter_move(
diff erent_reference_types_with_common_reference);
+};
+static_assert(check_indirectly_readable<
diff erent_reference_types_with_common_reference>());
+
+struct iter_ref4 {
+  operator iter_rvalue_ref() const;
+};
+namespace std {
+template <template <class> class XQual, template <class> class YQual>
+struct basic_common_reference<iter_ref4, iter_rvalue_ref, XQual, YQual> {
+  using type = iter_rvalue_ref;
+};
+template <template <class> class XQual, template <class> class YQual>
+struct basic_common_reference<iter_rvalue_ref, iter_ref4, XQual, YQual> {
+  using type = iter_rvalue_ref;
+};
+
+template <>
+struct common_reference<iter_ref4 const&, iter_rvalue_ref&&> {};
+template <>
+struct common_reference<iter_rvalue_ref&&, iter_ref4 const&> {};
+} // namespace std
+static_assert(std::common_reference_with<iter_ref4&&, iter_rvalue_ref&&>);
+static_assert(!std::common_reference_with<iter_ref4 const&, iter_rvalue_ref&&>);
+
+struct 
diff erent_reference_types_without_common_reference_to_const {
+  using value_type = iter_ref4;
+  iter_ref4& operator*() const;
+  friend iter_rvalue_ref&& iter_move(
diff erent_reference_types_without_common_reference_to_const);
+};
+static_assert(!check_indirectly_readable<
diff erent_reference_types_without_common_reference_to_const>());
+
+struct non_const_deref {
+  int& operator*();
+};
+static_assert(!check_indirectly_readable<non_const_deref>());
+
+struct not_referenceable {
+  using value_type = void;
+  void operator*() const;
+};
+static_assert(!std::indirectly_readable<not_referenceable>);
+
+struct legacy_output_iterator {
+  using value_type = void;
+  legacy_output_iterator& operator*();
+};
+
+static_assert(!std::indirectly_readable<legacy_output_iterator>);
+
+struct S {};
+static_assert(!std::indirectly_readable<S>);
+static_assert(!std::indirectly_readable<int S::*>);
+static_assert(!std::indirectly_readable<int (S::*)()>);
+static_assert(!std::indirectly_readable<int (S::*)() noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() &>);
+static_assert(!std::indirectly_readable<int (S::*)() & noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() &&>);
+static_assert(!std::indirectly_readable < int (S::*)() && noexcept >);
+static_assert(!std::indirectly_readable<int (S::*)() const>);
+static_assert(!std::indirectly_readable<int (S::*)() const noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() const&>);
+static_assert(!std::indirectly_readable<int (S::*)() const & noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() const&&>);
+static_assert(!std::indirectly_readable < int (S::*)() const&& noexcept >);
+static_assert(!std::indirectly_readable<int (S::*)() volatile>);
+static_assert(!std::indirectly_readable<int (S::*)() volatile noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() volatile&>);
+static_assert(!std::indirectly_readable<int (S::*)() volatile & noexcept>);
+static_assert(!std::indirectly_readable<int (S::*)() volatile&&>);
+static_assert(!std::indirectly_readable < int (S::*)() volatile&& noexcept >);

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp
new file mode 100644
index 000000000000..8f46ae06878d
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// template<class In>
+// concept indirectly_writable;
+
+#include <iterator>
+
+#include <concepts>
+#include <memory>
+#include <optional>
+
+#include "read_write.h"
+
+template <class Out, class T>
+[[nodiscard]] constexpr bool check_indirectly_writable() {
+  constexpr bool result = std::indirectly_writable<Out, T>;
+  static_assert(std::indirectly_writable<Out const, T> == result);
+  return result;
+}
+
+static_assert(check_indirectly_writable<value_type_indirection, int>());
+static_assert(check_indirectly_writable<value_type_indirection, double>());
+static_assert(!check_indirectly_writable<value_type_indirection, double*>());
+
+static_assert(!check_indirectly_writable<read_only_indirection, int>());
+static_assert(!check_indirectly_writable<proxy_indirection, int>());
+
+static_assert(!check_indirectly_writable<int, int>());
+static_assert(!check_indirectly_writable<missing_dereference, missing_dereference::value_type>());
+
+static_assert(!check_indirectly_writable<void*, int>());
+static_assert(!check_indirectly_writable<void const*, int>());
+static_assert(!check_indirectly_writable<void volatile*, int>());
+static_assert(!check_indirectly_writable<void const volatile*, int>());
+static_assert(!check_indirectly_writable<void*, double>());
+static_assert(check_indirectly_writable<void**, int*>());
+static_assert(!check_indirectly_writable<void**, int>());
+
+static_assert(check_indirectly_writable<int*, int>());
+static_assert(!check_indirectly_writable<int const*, int>());
+static_assert(check_indirectly_writable<int volatile*, int>());
+static_assert(!check_indirectly_writable<int const volatile*, int>());
+static_assert(check_indirectly_writable<int*, double>());
+static_assert(check_indirectly_writable<int**, int*>());
+static_assert(!check_indirectly_writable<int**, int>());

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..ae16543ac445
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// back_insert_iterator
+
+#include <iterator>
+
+#include <vector>
+
+using iterator = std::back_insert_iterator<std::vector<int> >;
+static_assert(!std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..c2521e0efeed
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// front_insert_iterator
+
+#include <iterator>
+
+#include <list>
+
+using iterator = std::front_insert_iterator<std::list<int> >;
+static_assert(!std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..d2e5ca96e3f6
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// insert_iterator
+
+#include <iterator>
+
+#include <vector>
+
+using iterator = std::insert_iterator<std::vector<int> >;
+static_assert(!std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..4d7af7a16bb0
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// move_iterator
+
+#include <iterator>
+
+using iterator = std::move_iterator<int*>;
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..6a79ec93a0a0
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// reverse_iterator
+
+#include <iterator>
+
+using iterator = std::reverse_iterator<int*>;
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..9a8daf5bfbb9
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// istream_iterator
+
+#include <iterator>
+
+#include <iosfwd>
+
+using iterator = std::istream_iterator<int, std::istream>;
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..fac71e2422dd
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// istreambuf_iterator
+
+#include <iterator>
+
+#include <istream>
+#include <string>
+
+using iterator = std::istreambuf_iterator<char>;
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, char>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..a3c135fb83b5
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// ostream_iterator
+
+#include <iterator>
+
+#include <iosfwd>
+
+using iterator = std::ostream_iterator<int, std::ostream>;
+static_assert(!std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, int>);

diff  --git a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..8f70b8e87db7
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// ostreambuf_iterator
+
+#include <iterator>
+
+#include <ostream>
+#include <string>
+
+using iterator = std::ostreambuf_iterator<char>;
+static_assert(!std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, char>);

diff  --git a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..5a655f39b808
--- /dev/null
+++ b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// regex_iterator
+
+#include <regex>
+
+#include <iterator>
+
+static_assert(std::indirectly_readable<std::cregex_iterator>);
+static_assert(!std::indirectly_writable<std::cregex_iterator, char>);

diff  --git a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..33a58e47397e
--- /dev/null
+++ b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// regex_token_iterator
+
+#include <regex>
+
+#include <iterator>
+
+static_assert(std::indirectly_readable<std::cregex_token_iterator>);
+static_assert(!std::indirectly_writable<std::cregex_token_iterator, char>);

diff  --git a/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..be8edeac9a80
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <string>
+
+#include <iterator>
+
+using iterator = std::string::iterator;
+using const_iterator = std::string::const_iterator;
+using value_type = iterator::value_type;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(std::indirectly_writable<iterator, value_type>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, value_type>);

diff  --git a/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..d4d362be8415
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.iterators/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <string_view>
+
+#include <iterator>
+
+using iterator = std::string_view::iterator;
+using const_iterator = std::string_view::const_iterator;
+
+static_assert(std::indirectly_readable<iterator>);
+static_assert(!std::indirectly_writable<iterator, char>);
+
+static_assert(std::indirectly_readable<const_iterator>);
+static_assert(!std::indirectly_writable<const_iterator, char>);

diff  --git a/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..7bc6536858d7
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/unique.ptr/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// unique_ptr
+
+#include <memory>
+
+#include <iterator>
+
+static_assert(std::indirectly_readable<std::unique_ptr<int> >);
+static_assert(std::indirectly_writable<std::unique_ptr<int>, int>);
+
+static_assert(!std::indirectly_readable<std::unique_ptr<void> >);
+static_assert(!std::indirectly_writable<std::unique_ptr<void>, void>);

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..6ef97e20b5d0
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// shared_ptr
+
+#include <memory>
+
+#include <iterator>
+
+static_assert(std::indirectly_readable<std::shared_ptr<int> >);
+static_assert(std::indirectly_writable<std::shared_ptr<int>, int>);
+
+static_assert(!std::indirectly_readable<std::shared_ptr<void> >);
+static_assert(!std::indirectly_writable<std::shared_ptr<void>, void>);

diff  --git a/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 000000000000..6129e72310de
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// unique_ptr
+
+#include <optional>
+
+#include <iterator>
+
+static_assert(!std::indirectly_readable<std::optional<int> >);
+static_assert(!std::indirectly_writable<std::optional<int>, int>);

diff  --git a/libcxx/test/support/read_write.h b/libcxx/test/support/read_write.h
new file mode 100644
index 000000000000..8736d1840eae
--- /dev/null
+++ b/libcxx/test/support/read_write.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_TEST_SUPPORT_READ_WRITE_H
+#define LIBCPP_TEST_SUPPORT_READ_WRITE_H
+
+struct value_type_indirection {
+  using value_type = int;
+  value_type& operator*() const;
+};
+
+struct element_type_indirection {
+  using element_type = long;
+  element_type& operator*() const;
+};
+
+struct proxy_indirection {
+  using value_type = int;
+  value_type operator*() const;
+};
+
+struct read_only_indirection {
+  using value_type = int const;
+  value_type& operator*() const;
+};
+
+// doubles as missing_iter_reference_t
+struct missing_dereference {
+  using value_type = int;
+};
+
+#endif // LIBCPP_TEST_SUPPORT_READ_WRITE_H


        


More information about the libcxx-commits mailing list