diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -84,6 +84,21 @@
     { __i++ } -> same_as<_Ip>;
   };
 
+// [iterator.concept.iterator]
+template<class _Ip>
+concept input_or_output_iterator =
+  requires(_Ip __i) {
+    { *__i } -> __referenceable;
+  } &&
+  weakly_incrementable<_Ip>;
+
+// [iterator.concept.sentinel]
+template<class _Sp, class _Ip>
+concept sentinel_for =
+  semiregular<_Sp> &&
+  input_or_output_iterator<_Ip> &&
+  __weakly_equality_comparable_with<_Sp, _Ip>;
+
 // clang-format on
 
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
diff --git a/libcxx/include/iterator b/libcxx/include/iterator
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -60,6 +60,14 @@
 template<class I>
   concept incrementable = see below;                       // since C++20
 
+// [iterator.concept.iterator], concept input_­or_­output_­iterator
+  template<class I>
+    concept input_or_output_iterator = see below;          // since C++20
+
+// [iterator.concept.sentinel], concept sentinel_­for
+template<class S, class I>
+  concept sentinel_for = see below;                        // since C++20
+
 template<class Category, class T, class Distance = ptrdiff_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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::map<int, int>::iterator;
 using const_iterator = std::map<int, int>::const_iterator;
+using reverse_iterator = std::map<int, int>::reverse_iterator;
+using const_reverse_iterator = std::map<int, int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::multimap<int, int>::iterator;
 using const_iterator = std::multimap<int, int>::const_iterator;
+using reverse_iterator = std::multimap<int, int>::reverse_iterator;
+using const_reverse_iterator = std::multimap<int, int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,22 @@
 
 using iterator = std::multiset<int>::iterator;
 using const_iterator = std::multiset<int>::const_iterator;
+using reverse_iterator = std::multiset<int>::reverse_iterator;
+using const_reverse_iterator = std::multiset<int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::set<int>::iterator;
 using const_iterator = std::set<int>::const_iterator;
+using reverse_iterator = std::set<int>::reverse_iterator;
+using const_reverse_iterator = std::set<int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,11 +19,23 @@
 
 using iterator = std::array<int, 10>::iterator;
 using const_iterator = std::array<int, 10>::const_iterator;
+using reverse_iterator = std::array<int, 10>::reverse_iterator;
+using const_reverse_iterator = std::array<int, 10>::const_reverse_iterator;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, int>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::deque<int>::iterator;
 using const_iterator = std::deque<int>::const_iterator;
+using reverse_iterator = std::deque<int>::reverse_iterator;
+using const_reverse_iterator = std::deque<int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -24,7 +24,13 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::list<int>::iterator;
 using const_iterator = std::list<int>::const_iterator;
+using reverse_iterator = std::list<int>::reverse_iterator;
+using const_reverse_iterator = std::list<int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::vector<bool>::iterator;
 using const_iterator = std::vector<bool>::const_iterator;
+using reverse_iterator = std::vector<bool>::reverse_iterator;
+using const_reverse_iterator = std::vector<bool>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,12 +19,24 @@
 
 using iterator = std::vector<int>::iterator;
 using const_iterator = std::vector<int>::const_iterator;
+using reverse_iterator = std::vector<int>::reverse_iterator;
+using const_reverse_iterator = std::vector<int>::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -26,15 +26,32 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, local_iterator>);
+static_assert(!std::sentinel_for<iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(!std::sentinel_for<const_iterator, local_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
-static_assert(!std::indirectly_writable<local_iterator, value_type>);
 static_assert(std::incrementable<local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<local_iterator, iterator>);
+static_assert(!std::sentinel_for<local_iterator, const_iterator>);
+static_assert(std::sentinel_for<local_iterator, local_iterator>);
+static_assert(std::sentinel_for<local_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
 static_assert(std::incrementable<const_local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, const_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, local_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, const_local_iterator>);
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
--- 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
@@ -26,15 +26,35 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, local_iterator>);
+static_assert(!std::sentinel_for<iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, local_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(!std::indirectly_writable<local_iterator, value_type>);
 static_assert(std::incrementable<local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<local_iterator, iterator>);
+static_assert(!std::sentinel_for<local_iterator, const_iterator>);
+static_assert(std::sentinel_for<local_iterator, local_iterator>);
+static_assert(std::sentinel_for<local_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
 static_assert(std::incrementable<const_local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, const_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, local_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, const_local_iterator>);
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
--- 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
@@ -26,15 +26,35 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, local_iterator>);
+static_assert(!std::sentinel_for<iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, local_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
 static_assert(!std::indirectly_writable<local_iterator, value_type>);
 static_assert(std::incrementable<local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<local_iterator, iterator>);
+static_assert(!std::sentinel_for<local_iterator, const_iterator>);
+static_assert(std::sentinel_for<local_iterator, local_iterator>);
+static_assert(std::sentinel_for<local_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
 static_assert(std::incrementable<const_local_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, const_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, local_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, const_local_iterator>);
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
--- 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
@@ -26,15 +26,32 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, local_iterator>);
+static_assert(!std::sentinel_for<iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(!std::sentinel_for<const_iterator, local_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<local_iterator>);
-static_assert(!std::indirectly_writable<local_iterator, value_type>);
 static_assert(std::incrementable<local_iterator>);
+static_assert(std::input_or_output_iterator<local_iterator>);
+static_assert(!std::sentinel_for<local_iterator, iterator>);
+static_assert(!std::sentinel_for<local_iterator, const_iterator>);
+static_assert(std::sentinel_for<local_iterator, local_iterator>);
+static_assert(std::sentinel_for<local_iterator, const_local_iterator>);
 
 static_assert(std::indirectly_readable<const_local_iterator>);
 static_assert(!std::indirectly_writable<const_local_iterator, value_type>);
 static_assert(std::incrementable<const_local_iterator>);
+static_assert(std::input_or_output_iterator<const_local_iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, iterator>);
+static_assert(!std::sentinel_for<const_local_iterator, const_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, local_iterator>);
+static_assert(std::sentinel_for<const_local_iterator, const_local_iterator>);
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
--- 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
@@ -18,8 +18,12 @@
 #include <iterator>
 
 using iterator = std::span<int>::iterator;
+using reverse_iterator = std::span<int>::reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
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
--- 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
@@ -21,9 +21,13 @@
 static_assert(!std::indirectly_writable<fs::directory_iterator, fs::directory_iterator::value_type>);
 static_assert(std::weakly_incrementable<fs::directory_iterator>);
 static_assert(!std::incrementable<fs::directory_iterator>);
+static_assert(std::input_or_output_iterator<fs::directory_iterator>);
+static_assert(std::sentinel_for<fs::directory_iterator, fs::directory_iterator>);
 
 static_assert(std::indirectly_readable<fs::recursive_directory_iterator>);
 static_assert(
     !std::indirectly_writable<fs::recursive_directory_iterator, fs::recursive_directory_iterator::value_type>);
 static_assert(std::weakly_incrementable<fs::recursive_directory_iterator>);
 static_assert(!std::incrementable<fs::recursive_directory_iterator>);
+static_assert(std::input_or_output_iterator<fs::recursive_directory_iterator>);
+static_assert(std::sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: msvc && clang
+
+// template<class In>
+// concept input_or_output_iterator;
+
+#include <iterator>
+
+#include "test_iterators.h"
+
+static_assert(std::input_or_output_iterator<int*>);
+static_assert(std::input_or_output_iterator<int const*>);
+static_assert(std::input_or_output_iterator<int volatile*>);
+static_assert(std::input_or_output_iterator<int const volatile*>);
+
+static_assert(std::input_or_output_iterator<input_iterator<int*> >);
+static_assert(std::input_or_output_iterator<input_iterator<int const*> >);
+static_assert(std::input_or_output_iterator<input_iterator<int volatile*> >);
+static_assert(std::input_or_output_iterator<input_iterator<int const volatile*> >);
+
+static_assert(std::input_or_output_iterator<forward_iterator<int*> >);
+static_assert(std::input_or_output_iterator<forward_iterator<int const*> >);
+static_assert(std::input_or_output_iterator<forward_iterator<int volatile*> >);
+static_assert(std::input_or_output_iterator<forward_iterator<int const volatile*> >);
+
+static_assert(std::input_or_output_iterator<bidirectional_iterator<int*> >);
+static_assert(std::input_or_output_iterator<bidirectional_iterator<int const*> >);
+static_assert(std::input_or_output_iterator<bidirectional_iterator<int volatile*> >);
+static_assert(std::input_or_output_iterator<bidirectional_iterator<int const volatile*> >);
+
+static_assert(std::input_or_output_iterator<random_access_iterator<int*> >);
+static_assert(std::input_or_output_iterator<random_access_iterator<int const*> >);
+static_assert(std::input_or_output_iterator<random_access_iterator<int volatile*> >);
+static_assert(std::input_or_output_iterator<random_access_iterator<int const volatile*> >);
+
+static_assert(!std::input_or_output_iterator<void*>);
+static_assert(!std::input_or_output_iterator<void const*>);
+static_assert(!std::input_or_output_iterator<void volatile*>);
+static_assert(!std::input_or_output_iterator<void const volatile*>);
+
+struct S {};
+static_assert(!std::input_or_output_iterator<S>);
+static_assert(!std::input_or_output_iterator<int S::*>);
+static_assert(!std::input_or_output_iterator<int (S::*)()>);
+static_assert(!std::input_or_output_iterator<int (S::*)() const>);
+static_assert(!std::input_or_output_iterator<int (S::*)() volatile>);
+
+struct missing_dereference {
+  using difference_type = std::ptrdiff_t;
+
+  missing_dereference& operator++();
+  missing_dereference& operator++(int);
+};
+static_assert(std::weakly_incrementable<missing_dereference> && !std::input_or_output_iterator<missing_dereference>);
+
+struct void_dereference {
+  using difference_type = std::ptrdiff_t;
+
+  void operator*();
+  void_dereference& operator++();
+  void_dereference& operator++(int);
+};
+static_assert(std::weakly_incrementable<void_dereference> && !std::input_or_output_iterator<void_dereference>);
+
+struct not_weakly_incrementable {
+  int operator*() const;
+};
+static_assert(!std::input_or_output_iterator<not_weakly_incrementable>);
diff --git a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp
copy from libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
copy to libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp
--- a/libcxx/test/std/containers/views/span.iterators/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp
@@ -11,15 +11,21 @@
 // UNSUPPORTED: gcc-10
 // XFAIL: msvc && clang
 
-// iterator, reverse_iterator
-
-#include <span>
+// template<class In>
+// concept input_or_output_iterator;
 
 #include <iterator>
 
-using iterator = std::span<int>::iterator;
-using value_type = iterator::value_type;
+// clang-format off
+template<std::weakly_incrementable>
+[[nodiscard]] constexpr bool check_subsumption() {
+  return false;
+}
+
+template<std::input_or_output_iterator>
+[[nodiscard]] constexpr bool check_subsumption() {
+  return true;
+}
+// clang-format on
 
-static_assert(std::indirectly_readable<iterator>);
-static_assert(std::indirectly_writable<iterator, value_type>);
-static_assert(std::incrementable<iterator>);
+static_assert(check_subsumption<int*>());
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: msvc && clang
+
+// template<class S, class I>
+// concept sentinel_for;
+
+#include <iterator>
+
+static_assert(std::sentinel_for<int*, int*>);
+static_assert(!std::sentinel_for<int*, long*>);
+struct nth_element_sentinel {
+  bool operator==(int*) const;
+};
+static_assert(std::sentinel_for<nth_element_sentinel, int*>);
+static_assert(std::sentinel_for<nth_element_sentinel, int*>);
+
+struct not_semiregular {
+  not_semiregular() = delete;
+  bool operator==(int*) const;
+};
+static_assert(!std::sentinel_for<not_semiregular, int*>);
+
+struct weakly_equality_comparable_with_int {
+  bool operator==(int) const;
+};
+static_assert(!std::sentinel_for<weakly_equality_comparable_with_int, int>);
+
+struct move_only_iterator {
+  using value_type = int;
+  using difference_type = std::ptrdiff_t;
+
+  move_only_iterator() = default;
+
+  move_only_iterator(move_only_iterator&&) = default;
+  move_only_iterator& operator=(move_only_iterator&&) = default;
+
+  move_only_iterator(move_only_iterator const&) = delete;
+  move_only_iterator& operator=(move_only_iterator const&) = delete;
+
+  value_type operator*() const;
+  move_only_iterator& operator++();
+  move_only_iterator operator++(int);
+
+  bool operator==(move_only_iterator const&) const = default;
+};
+static_assert(std::movable<move_only_iterator> && !std::copyable<move_only_iterator> &&
+              std::input_or_output_iterator<move_only_iterator> &&
+              !std::sentinel_for<move_only_iterator, move_only_iterator>);
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/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp
copy from libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
copy to libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp
--- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/iterator_concept_conformance.compile.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp
@@ -11,13 +11,24 @@
 // UNSUPPORTED: gcc-10
 // XFAIL: msvc && clang
 
-// back_insert_iterator
+// template<class S, class I>
+// concept sentinel_for;
 
 #include <iterator>
 
+#include <concepts>
 #include <vector>
 
-using iterator = std::back_insert_iterator<std::vector<int> >;
-static_assert(!std::indirectly_readable<iterator>);
-static_assert(std::indirectly_writable<iterator, int>);
-static_assert(!std::weakly_incrementable<iterator>);
+// clang-format off
+template<std::input_or_output_iterator, std::semiregular>
+[[nodiscard]] constexpr bool check_sentinel_subsumption() {
+  return false;
+}
+
+template<class I, std::sentinel_for<I> >
+[[nodiscard]] constexpr bool check_subsumption() {
+  return true;
+}
+// clang-format on
+
+static_assert(check_subsumption<std::vector<int>::iterator, std::vector<int>::iterator>());
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
--- 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
@@ -21,3 +21,5 @@
 static_assert(!std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(!std::weakly_incrementable<iterator>);
+static_assert(!std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -21,3 +21,5 @@
 static_assert(!std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(!std::weakly_incrementable<iterator>);
+static_assert(!std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -21,3 +21,5 @@
 static_assert(!std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(!std::weakly_incrementable<iterator>);
+static_assert(!std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -19,3 +19,5 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, int>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -16,6 +16,12 @@
 #include <iterator>
 
 using iterator = std::reverse_iterator<int*>;
+
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+
+using other_iterator = std::reverse_iterator<float*>;
+static_assert(std::sentinel_for<iterator, other_iterator>);
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
--- 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
@@ -21,3 +21,5 @@
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, int>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -23,3 +23,5 @@
 static_assert(!std::indirectly_writable<iterator, char>);
 static_assert(std::weakly_incrementable<iterator>);
 static_assert(!std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -21,3 +21,5 @@
 static_assert(!std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, int>);
 static_assert(!std::weakly_incrementable<iterator>);
+static_assert(!std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -22,3 +22,5 @@
 static_assert(!std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, char>);
 static_assert(!std::weakly_incrementable<iterator>);
+static_assert(!std::input_or_output_iterator<iterator>);
+static_assert(!std::sentinel_for<iterator, iterator>);
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
--- 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
@@ -20,3 +20,5 @@
 static_assert(std::indirectly_readable<std::cregex_iterator>);
 static_assert(!std::indirectly_writable<std::cregex_iterator, char>);
 static_assert(std::incrementable<std::cregex_iterator>);
+static_assert(std::input_or_output_iterator<std::cregex_iterator>);
+static_assert(std::sentinel_for<std::cregex_iterator, std::cregex_iterator>);
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
--- 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
@@ -20,3 +20,5 @@
 static_assert(std::indirectly_readable<std::cregex_token_iterator>);
 static_assert(!std::indirectly_writable<std::cregex_token_iterator, char>);
 static_assert(std::incrementable<std::cregex_token_iterator>);
+static_assert(std::input_or_output_iterator<std::cregex_token_iterator>);
+static_assert(std::sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
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
--- 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
@@ -19,12 +19,23 @@
 
 using iterator = std::string::iterator;
 using const_iterator = std::string::const_iterator;
+using reverse_iterator = std::string::reverse_iterator;
+using const_reverse_iterator = std::string::const_reverse_iterator;
 using value_type = iterator::value_type;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(std::indirectly_writable<iterator, value_type>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, value_type>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
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
--- 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
@@ -19,11 +19,23 @@
 
 using iterator = std::string_view::iterator;
 using const_iterator = std::string_view::const_iterator;
+using reverse_iterator = std::string_view::reverse_iterator;
+using const_reverse_iterator = std::string_view::const_reverse_iterator;
 
 static_assert(std::indirectly_readable<iterator>);
 static_assert(!std::indirectly_writable<iterator, char>);
 static_assert(std::incrementable<iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<iterator, iterator>);
+static_assert(std::sentinel_for<iterator, const_iterator>);
+static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
 
 static_assert(std::indirectly_readable<const_iterator>);
 static_assert(!std::indirectly_writable<const_iterator, char>);
 static_assert(std::incrementable<const_iterator>);
+static_assert(std::input_or_output_iterator<iterator>);
+static_assert(std::sentinel_for<const_iterator, iterator>);
+static_assert(std::sentinel_for<const_iterator, const_iterator>);
+static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);