[libcxx-commits] [libcxx] [libc++][ranges] P3059R2: Making user-defined constructors of view iterators/sentinels private (PR #193891)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 22 03:32:57 PDT 2026


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/193891

>From 68da1731c2ad8f5e98872b8df5e8dd5bfa646008 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 3 Apr 2026 08:43:06 +0300
Subject: [PATCH 01/28] [libc++][ranges] P3059R2: Making user-defined
 constructors of view iterators/sentinels private

Implements https://wg21.link/P3059R2

Closes #189599
---
 libcxx/include/__ranges/elements_view.h   | 12 ++++++++----
 libcxx/include/__ranges/filter_view.h     | 20 ++++++++++++-------
 libcxx/include/__ranges/iota_view.h       | 15 ++++++++------
 libcxx/include/__ranges/istream_view.h    |  8 +++++---
 libcxx/include/__ranges/join_view.h       |  6 ++++--
 libcxx/include/__ranges/lazy_split_view.h | 24 +++++++++++++----------
 libcxx/include/__ranges/split_view.h      | 18 ++++++++++-------
 libcxx/include/__ranges/take_view.h       |  6 ++++--
 libcxx/include/__ranges/take_while_view.h |  8 +++++---
 libcxx/include/__ranges/transform_view.h  | 14 ++++++++-----
 10 files changed, 82 insertions(+), 49 deletions(-)

diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h
index 33c152bbd03b4..706744ae652e1 100644
--- a/libcxx/include/__ranges/elements_view.h
+++ b/libcxx/include/__ranges/elements_view.h
@@ -165,6 +165,8 @@ template <input_range _View, size_t _Np>
 template <bool _Const>
 class elements_view<_View, _Np>::__iterator
     : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> {
+  friend class elements_view<_View, _Np>;
+
   template <bool>
   friend class __iterator;
 
@@ -175,6 +177,8 @@ class elements_view<_View, _Np>::__iterator
 
   iterator_t<_Base> __current_ = iterator_t<_Base>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
+
   _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) {
     if constexpr (is_reference_v<range_reference_t<_Base>>) {
       return std::get<_Np>(*__i);
@@ -205,8 +209,6 @@ class elements_view<_View, _Np>::__iterator
     requires default_initializable<iterator_t<_Base>>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
     requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
       : __current_(std::move(__i.__current_)) {}
@@ -339,6 +341,10 @@ class elements_view<_View, _Np>::__sentinel {
   using _Base _LIBCPP_NODEBUG                        = __maybe_const<_Const, _View>;
   _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
+
+  friend class elements_view<_View, _Np>;
+
   template <bool>
   friend class __sentinel;
 
@@ -350,8 +356,6 @@ class elements_view<_View, _Np>::__sentinel {
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other)
     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
       : __end_(std::move(__other.__end_)) {}
diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h
index 7ec53dac4a84f..3004e830173f1 100644
--- a/libcxx/include/__ranges/filter_view.h
+++ b/libcxx/include/__ranges/filter_view.h
@@ -127,10 +127,16 @@ struct __filter_iterator_category<_View> {
 template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
   requires view<_View> && is_object_v<_Pred>
 class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> {
-public:
+private:
   _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>();
   _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_       = nullptr;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
+      : __current_(std::move(__current)), __parent_(std::addressof(__parent)) {}
+
+  friend class filter_view<_View, _Pred>;
+
+public:
   using iterator_concept =
       _If<bidirectional_range<_View>,
           bidirectional_iterator_tag,
@@ -145,9 +151,6 @@ class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<
     requires default_initializable<iterator_t<_View>>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
-      : __current_(std::move(__current)), __parent_(std::addressof(__parent)) {}
-
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> const& base() const& noexcept { return __current_; }
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() && { return std::move(__current_); }
 
@@ -211,13 +214,16 @@ class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<
 template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
   requires view<_View> && is_object_v<_Pred>
 class filter_view<_View, _Pred>::__sentinel {
-public:
+private:
   sentinel_t<_View> __end_ = sentinel_t<_View>();
 
-  _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
-
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(filter_view& __parent) : __end_(ranges::end(__parent.__base_)) {}
 
+  friend class filter_view<_View, _Pred>;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
+
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_View> base() const { return __end_; }
 
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(__iterator const& __x, __sentinel const& __y) {
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 38e0ccaf2849e..9d87138d29e23 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -110,6 +110,12 @@ template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_
   requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
 class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
   struct __iterator : public __iota_iterator_category<_Start> {
+  private:
+    _Start __value_ = _Start();
+
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
+
+  public:
     friend class iota_view;
 
     using iterator_concept =
@@ -124,14 +130,10 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
     using value_type      = _Start;
     using difference_type = _IotaDiffT<_Start>;
 
-    _Start __value_ = _Start();
-
     _LIBCPP_HIDE_FROM_ABI __iterator()
       requires default_initializable<_Start>
     = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
-
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Start operator*() const
         noexcept(is_nothrow_copy_constructible_v<_Start>) {
       return __value_;
@@ -282,11 +284,12 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
   private:
     _BoundSentinel __bound_sentinel_ = _BoundSentinel();
 
-  public:
-    _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel)
         : __bound_sentinel_(std::move(__bound_sentinel)) {}
 
+  public:
+    _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
+
     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
       return __x.__value_ == __y.__bound_sentinel_;
     }
diff --git a/libcxx/include/__ranges/istream_view.h b/libcxx/include/__ranges/istream_view.h
index 7c64463108e1a..1bee6e69f2186 100644
--- a/libcxx/include/__ranges/istream_view.h
+++ b/libcxx/include/__ranges/istream_view.h
@@ -66,9 +66,6 @@ class basic_istream_view<_Val, _CharT, _Traits>::__iterator {
   using difference_type  = ptrdiff_t;
   using value_type       = _Val;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
-      : __parent_(std::addressof(__parent)) {}
-
   __iterator(const __iterator&)                  = delete;
   _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default;
 
@@ -91,9 +88,14 @@ class basic_istream_view<_Val, _CharT, _Traits>::__iterator {
 private:
   basic_istream_view<_Val, _CharT, _Traits>* __parent_;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
+      : __parent_(std::addressof(__parent)) {}
+
   _LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const {
     return __parent_->__stream_;
   }
+
+  friend class basic_istream_view<_Val, _CharT, _Traits>;
 };
 
 template <class _Val>
diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h
index f80b75c839d4a..4f3f8d1c1e5b4 100644
--- a/libcxx/include/__ranges/join_view.h
+++ b/libcxx/include/__ranges/join_view.h
@@ -160,11 +160,13 @@ struct join_view<_View>::__sentinel {
   using _Base _LIBCPP_NODEBUG   = __maybe_const<_Const, _View>;
   sentinel_t<_Base> __end_      = sentinel_t<_Base>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {}
+
+  friend class join_view<_View>;
+
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
       : __end_(std::move(__s.__end_)) {}
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index be2b86772fa0d..9c44d26faf1e7 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -143,6 +143,8 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
   template <bool _Const>
   struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> {
   private:
+    friend class lazy_split_view<_View, _Pattern>;
+
     template <bool>
     friend struct __inner_iterator;
     friend __outer_iterator<true>;
@@ -155,6 +157,14 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
     _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent();
     bool __trailing_empty_                             = false;
 
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(_Parent& __parent)
+      requires(!forward_range<_Base>)
+        : __parent_(std::addressof(__parent)) {}
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current)
+      requires forward_range<_Base>
+        : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
+
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto& __current() noexcept {
       if constexpr (forward_range<_View>) {
         return __current_;
@@ -196,14 +206,6 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
 
     _LIBCPP_HIDE_FROM_ABI __outer_iterator() = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(_Parent& __parent)
-      requires(!forward_range<_Base>)
-        : __parent_(std::addressof(__parent)) {}
-
-    _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current)
-      requires forward_range<_Base>
-        : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
-
     _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(__outer_iterator<!_Const> __i)
       requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
         : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}
@@ -286,12 +288,16 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
   template <bool _Const>
   struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> {
   private:
+    friend class lazy_split_view<_View, _Pattern>;
+
     using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
     // Workaround for a GCC issue.
     static constexpr bool _OuterConst = _Const;
     __outer_iterator<_Const> __i_     = __outer_iterator<_OuterConst>();
     bool __incremented_               = false;
 
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {}
+
     // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from
     // free functions that are friends of `inner-iterator`.
 
@@ -342,8 +348,6 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
 
     _LIBCPP_HIDE_FROM_ABI __inner_iterator() = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {}
-
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept {
       return __i_.__current();
     }
diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h
index 10148e0e64764..7295e33a282f0 100644
--- a/libcxx/include/__ranges/split_view.h
+++ b/libcxx/include/__ranges/split_view.h
@@ -127,6 +127,12 @@ struct split_view<_View, _Pattern>::__iterator {
   _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>();
   bool __trailing_empty_                                        = false;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(
+      split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
+      : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}
+
+  friend class split_view<_View, _Pattern>;
+
   friend struct __sentinel;
 
 public:
@@ -137,10 +143,6 @@ struct split_view<_View, _Pattern>::__iterator {
 
   _LIBCPP_HIDE_FROM_ABI __iterator() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(
-      split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
-      : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}
-
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; }
@@ -179,16 +181,18 @@ struct split_view<_View, _Pattern>::__sentinel {
 private:
   _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
+      : __end_(ranges::end(__parent.__base_)) {}
+
   _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) {
     return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_;
   }
 
+  friend class split_view<_View, _Pattern>;
+
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
-      : __end_(ranges::end(__parent.__base_)) {}
-
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
     return __equals(__x, __y);
   }
diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h
index 999f686537f2c..ee62d49f71d8b 100644
--- a/libcxx/include/__ranges/take_view.h
+++ b/libcxx/include/__ranges/take_view.h
@@ -165,14 +165,16 @@ class take_view<_View>::__sentinel {
   using _Iter _LIBCPP_NODEBUG                        = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>;
   _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
+
+  friend class take_view<_View>;
+
   template <bool>
   friend class take_view<_View>::__sentinel;
 
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
       : __end_(std::move(__s.__end_)) {}
diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h
index 0aee306807c8b..e77b79665d1f6 100644
--- a/libcxx/include/__ranges/take_while_view.h
+++ b/libcxx/include/__ranges/take_while_view.h
@@ -108,14 +108,16 @@ class take_while_view<_View, _Pred>::__sentinel {
   sentinel_t<_Base> __end_ = sentinel_t<_Base>();
   const _Pred* __pred_     = nullptr;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
+      : __end_(std::move(__end)), __pred_(__pred) {}
+
+  friend class take_while_view<_View, _Pred>;
+
   friend class __sentinel<!_Const>;
 
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
-      : __end_(std::move(__end)), __pred_(__pred) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
       : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {}
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index 06ace86bbfafa..807f1cf19a0ac 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -192,6 +192,11 @@ class transform_view<_View, _Fn>::__iterator
 
   _Parent* __parent_ = nullptr;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
+      : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
+
+  friend class transform_view<_View, _Fn>;
+
   template <bool>
   friend class transform_view<_View, _Fn>::__iterator;
 
@@ -209,9 +214,6 @@ class transform_view<_View, _Fn>::__iterator
     requires default_initializable<iterator_t<_Base>>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
-      : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
-
   // Note: `__i` should always be `__iterator<false>`, but directly using
   // `__iterator<false>` is ill-formed when `_Const` is false
   // (see http://wg21.link/class.copy.ctor#5).
@@ -354,6 +356,10 @@ class transform_view<_View, _Fn>::__sentinel {
 
   sentinel_t<_Base> __end_ = sentinel_t<_Base>();
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
+
+  friend class transform_view<_View, _Fn>;
+
   template <bool>
   friend class transform_view<_View, _Fn>::__iterator;
 
@@ -363,8 +369,6 @@ class transform_view<_View, _Fn>::__sentinel {
 public:
   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
-
   // Note: `__i` should always be `__sentinel<false>`, but directly using
   // `__sentinel<false>` is ill-formed when `_Const` is false
   // (see http://wg21.link/class.copy.ctor#5).

>From c4d11be4adc7c07fd52f608bea12da28e8221371 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 6 Apr 2026 00:45:01 +0300
Subject: [PATCH 02/28] Tests: `split_view`

---
 .../range.split/iterator/base.pass.cpp        | 28 +++++++++++++------
 .../range.split/iterator/ctor.base.pass.cpp   |  4 +--
 .../range.split/iterator/deref.pass.cpp       | 28 ++++++++++++-------
 .../range.split/sentinel/ctor.parent.pass.cpp |  5 +---
 4 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
index 325189a0e521e..66c2914ba1919 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
@@ -16,9 +16,20 @@
 #include "../types.h"
 
 struct Iter : ForwardIterBase<Iter> {
-  int i;
+  int i = 0;
   constexpr Iter() = default;
   constexpr Iter(int ii) : i(ii) {}
+  constexpr int operator*() const { return i; }
+  constexpr Iter& operator++() {
+    ++i;
+    return *this;
+  }
+  constexpr Iter operator++(int) {
+    Iter tmp = *this;
+    ++*this;
+    return tmp;
+  }
+  friend constexpr bool operator==(const Iter& x, const Iter& y) { return x.i == y.i; }
 };
 
 constexpr bool test() {
@@ -26,34 +37,33 @@ constexpr bool test() {
   using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
   using SplitIter = std::ranges::iterator_t<SplitView>;
 
+  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}},
+               std::ranges::subrange<Iter>{Iter{8}, Iter{9}}};
+
   // const &
   {
-    SplitView sv;
-    const SplitIter it{sv, Iter{5}, {}};
+    const SplitIter it = sv.begin();
     std::same_as<Iter> decltype(auto) base = it.base();
     assert(base.i == 5);
   }
 
   // &
   {
-    SplitView sv;
-    SplitIter it{sv, Iter{5}, {}};
+    SplitIter it = sv.begin();
     std::same_as<Iter> decltype(auto) base = it.base();
     assert(base.i == 5);
   }
 
   // &&
   {
-    SplitView sv;
-    SplitIter it{sv, Iter{5}, {}};
+    SplitIter it = sv.begin();
     std::same_as<Iter> decltype(auto) base = std::move(it).base();
     assert(base.i == 5);
   }
 
   // const &&
   {
-    SplitView sv;
-    const SplitIter it{sv, Iter{5}, {}};
+    const SplitIter it = sv.begin();
     std::same_as<Iter> decltype(auto) base = std::move(it).base();
     assert(base.i == 5);
   }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp
index 20b3c19611bd0..823e22e117f77 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
+// constexpr iterator begin();
 
 #include <cassert>
 #include <ranges>
@@ -35,7 +35,7 @@ constexpr bool test() {
   using SplitIter = std::ranges::iterator_t<SplitView>;
 
   SplitView sv{TracedMoveView{}, TracedMoveView{}};
-  SplitIter iter = {sv, sv.base().begin(), std::ranges::subrange<TracedMoveIter>{sv.base().begin(), sv.base().end()}};
+  SplitIter iter = sv.begin();
   assert(iter.base().moved);
 
   auto subRange = *iter;
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
index 721a1cc0da3d4..be7aca854f640 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
@@ -17,24 +17,32 @@
 #include "../types.h"
 
 struct Iter : ForwardIterBase<Iter> {
-  int i;
+  int i = 0;
   constexpr Iter() = default;
   constexpr Iter(int ii) : i(ii) {}
+  constexpr int operator*() const { return i; }
+  constexpr Iter& operator++() {
+    ++i;
+    return *this;
+  }
+  constexpr Iter operator++(int) {
+    Iter tmp = *this;
+    ++*this;
+    return tmp;
+  }
+  friend constexpr bool operator==(const Iter& x, const Iter& y) { return x.i == y.i; }
 };
 
 constexpr bool test() {
   using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
   using SplitIter = std::ranges::iterator_t<SplitView>;
 
-  {
-    SplitView sv;
-    Iter current{5};
-    std::ranges::subrange next{Iter{6}, Iter{7}};
-    const SplitIter it{sv, current, next};
-    std::same_as<std::ranges::subrange<Iter>> decltype(auto) value = *it;
-    assert(value.begin().i == 5);
-    assert(value.end().i == 6);
-  }
+  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}},
+               std::ranges::subrange<Iter>{Iter{7}, Iter{8}}};
+  const SplitIter it = sv.begin();
+  std::same_as<std::ranges::subrange<Iter>> decltype(auto) value = *it;
+  assert(value.begin().i == 5);
+  assert(value.end().i == 7);
 
   return true;
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp
index c89b1ee2bdfce..6e1ba912a201b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp
@@ -21,9 +21,6 @@ using Range     = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
 using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
 using SplitSent = std::ranges::sentinel_t<SplitView>;
 
-static_assert(std::is_constructible_v<SplitSent, SplitView&>);
-static_assert(!std::is_convertible_v<SplitView&, SplitSent>);
-
 constexpr bool test() {
   {
     int buffer[] = {0, 1, 2};
@@ -31,7 +28,7 @@ constexpr bool test() {
     SplitView sv(input, -1);
     auto it = sv.begin();
 
-    SplitSent sent(sv);
+    auto sent = sv.end();
     assert(sent != it);
 
     ++it;

>From 781eaa5dbef3351d87574cf432106a2a7d7c9a38 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 6 Apr 2026 00:48:57 +0300
Subject: [PATCH 03/28] Tests: `take_view`

---
 .../range.take/range.take.sentinel/ctor.pass.cpp    | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.pass.cpp
index 61d33760c71d7..3710be563c15b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.pass.cpp
@@ -9,7 +9,6 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
 // sentinel() = default;
-// constexpr explicit sentinel(sentinel_t<Base> end);
 // constexpr sentinel(sentinel<!Const> s)
 //   requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
@@ -49,18 +48,6 @@ constexpr bool test() {
     assert(std::as_const(tv).begin() + 4 == cs);
   }
 
-  {
-    // Test the constructor from "base-sentinel" to "sentinel".
-    using TakeView             = std::ranges::take_view<MoveOnlyView>;
-    using Sentinel             = std::ranges::sentinel_t<TakeView>;
-    sentinel_wrapper<int*> sw1 = MoveOnlyView(buffer).end();
-    static_assert(std::is_constructible_v<Sentinel, sentinel_wrapper<int*>>);
-    static_assert(!std::is_convertible_v<sentinel_wrapper<int*>, Sentinel>);
-    auto s                                        = Sentinel(sw1);
-    std::same_as<sentinel_wrapper<int*>> auto sw2 = s.base();
-    assert(base(sw2) == base(sw1));
-  }
-
   return true;
 }
 

>From 195931a66e133699188de65ed5b8ee7f9aef2fe7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 12:41:47 +0300
Subject: [PATCH 04/28] Tests: `take_while_view`

---
 .../sentinel/ctor.base.pass.cpp               | 86 -------------------
 .../sentinel/ctor.convert.pass.cpp            | 43 +++++++---
 2 files changed, 31 insertions(+), 98 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pass.cpp
deleted file mode 100644
index b952534d1c966..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pass.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
-
-#include <cassert>
-#include <ranges>
-#include <utility>
-
-#include "../types.h"
-
-struct Sent {
-  int i;
-
-  friend constexpr bool operator==(int* iter, const Sent& s) { return s.i > *iter; }
-};
-
-struct Range : std::ranges::view_base {
-  int* begin() const;
-  Sent end();
-};
-
-struct Pred {
-  bool operator()(int i) const;
-};
-
-// Test explicit
-template <class T>
-void conversion_test(T);
-
-template <class T, class... Args>
-concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
-static_assert(ImplicitlyConstructible<int, int>);
-
-static_assert(std::is_constructible_v<std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>,
-                                      std::ranges::sentinel_t<Range>,
-                                      const Pred*>);
-static_assert(!ImplicitlyConstructible<std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>,
-                                       std::ranges::sentinel_t<Range>,
-                                       const Pred*>);
-
-constexpr bool test() {
-  // base is init correctly
-  {
-    using R        = std::ranges::take_while_view<Range, bool (*)(int)>;
-    using Sentinel = std::ranges::sentinel_t<R>;
-
-    Sentinel s1(Sent{5}, nullptr);
-    assert(s1.base().i == 5);
-  }
-
-  // pred is init correctly
-  {
-    bool called = false;
-    auto pred   = [&](int) {
-      called = true;
-      return false;
-    };
-
-    using R        = std::ranges::take_while_view<Range, decltype(pred)>;
-    using Sentinel = std::ranges::sentinel_t<R>;
-
-    int i     = 10;
-    int* iter = &i;
-    Sentinel s(Sent{0}, &pred);
-
-    bool b = iter == s;
-    assert(called);
-    assert(b);
-  }
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
index 865a3d45710fb..0fffe9b508816 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
@@ -70,34 +70,48 @@ static_assert(!std::is_constructible_v<
 constexpr bool test() {
   // base is init correctly
   {
-    using R             = std::ranges::take_while_view<Range, bool (*)(int)>;
+    struct TestRng : std::ranges::view_base {
+      constexpr int* begin() const { return nullptr; }
+      constexpr Sent end() { return Sent{5}; }
+      constexpr ConstSent end() const { return ConstSent{5}; }
+    };
+
+    using R             = std::ranges::take_while_view<TestRng, bool (*)(int)>;
     using Sentinel      = std::ranges::sentinel_t<R>;
     using ConstSentinel = std::ranges::sentinel_t<const R>;
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
-    Sentinel s1(Sent{5}, nullptr);
+    R r{TestRng{}, nullptr};
+    Sentinel s1 = r.end();
     ConstSentinel s2 = s1;
     assert(s2.base().i == 5);
   }
 
   // pred is init correctly
   {
+    struct TestRng : std::ranges::view_base {
+      constexpr int* begin() const { return nullptr; }
+      constexpr Sent end() { return Sent{0}; }
+      constexpr ConstSent end() const { return ConstSent{0}; }
+    };
+
     bool called = false;
     auto pred   = [&](int) {
       called = true;
       return false;
     };
 
-    using R             = std::ranges::take_while_view<Range, decltype(pred)>;
+    using R             = std::ranges::take_while_view<TestRng, decltype(pred)>;
     using Sentinel      = std::ranges::sentinel_t<R>;
     using ConstSentinel = std::ranges::sentinel_t<const R>;
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
-    int i     = 10;
-    int* iter = &i;
-    Sentinel s1(Sent{0}, &pred);
+    R r{TestRng{}, pred};
+    Sentinel s1 = r.end();
     ConstSentinel s2 = s1;
 
+    int i     = 10;
+    int* iter = &i;
     [[maybe_unused]] bool b = iter == s2;
     assert(called);
   }
@@ -111,20 +125,25 @@ constexpr bool test() {
       constexpr bool operator==(int* iter) const { return i > *iter; }
     };
 
+    struct TestPred {
+      constexpr bool operator()(int) const { return false; }
+    };
+
     struct Rng : std::ranges::view_base {
-      int* begin() const;
-      Sent end();
-      MoveOnlyConvert end() const;
+      constexpr int* begin() const { return nullptr; }
+      constexpr Sent end() { return Sent{0}; }
+      constexpr MoveOnlyConvert end() const { return MoveOnlyConvert(Sent{0}); }
     };
 
-    using R             = std::ranges::take_while_view<Rng, Pred>;
+    using R             = std::ranges::take_while_view<Rng, TestPred>;
     using Sentinel      = std::ranges::sentinel_t<R>;
     using ConstSentinel = std::ranges::sentinel_t<const R>;
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
-    Sentinel s1(Sent{5}, nullptr);
+    R r{Rng{}, TestPred{}};
+    Sentinel s1 = r.end();
     ConstSentinel s2 = s1;
-    assert(s2.base().i == 5);
+    assert(s2.base().i == 0);
   }
 
   return true;

>From 26cf1daff36cae1d3e5f5476f7faba71cb019296 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 12:58:00 +0300
Subject: [PATCH 05/28] Tests: `filter_view`

---
 .../range.filter/iterator/arrow.pass.cpp      |  3 +-
 .../range.filter/iterator/base.pass.cpp       |  4 +-
 .../iterator/ctor.parent_iter.pass.cpp        | 51 ----------------
 .../range.filter/iterator/deref.pass.cpp      |  3 +-
 .../sentinel/ctor.parent.pass.cpp             | 60 -------------------
 5 files changed, 6 insertions(+), 115 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent_iter.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
index 8a12b1694ca2f..46d59c3de1d7d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
@@ -87,7 +87,8 @@ constexpr void test() {
 
   for (std::ptrdiff_t n = 0; n != 5; ++n) {
     FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
-    FilterIterator const iter(view, Iter(array.data() + n));
+    FilterIterator iter = view.begin();
+    for (std::ptrdiff_t i = 0; i < n; ++i) ++iter;
     std::same_as<Iter> decltype(auto) result = iter.operator->();
     assert(base(result) == array.data() + n);
     assert(iter->x == n);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/base.pass.cpp
index 813cd892c64e6..9f193ddbc1a2d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/base.pass.cpp
@@ -37,7 +37,7 @@ constexpr void test() {
 
   // Test the const& version
   {
-    FilterIterator const iter(view, Iter(array.data()));
+    FilterIterator const iter = view.begin();
     Iter const& result = iter.base();
     ASSERT_SAME_TYPE(Iter const&, decltype(iter.base()));
     ASSERT_NOEXCEPT(iter.base());
@@ -46,7 +46,7 @@ constexpr void test() {
 
   // Test the && version
   {
-    FilterIterator iter(view, Iter(array.data()));
+    FilterIterator iter = view.begin();
     Iter result = std::move(iter).base();
     ASSERT_SAME_TYPE(Iter, decltype(std::move(iter).base()));
     assert(base(result) == array.data());
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent_iter.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent_iter.pass.cpp
deleted file mode 100644
index 761ef2d8ee493..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent_iter.pass.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr std::ranges::filter_view::<iterator>(filter_view&, iterator_t<V>);
-
-#include <ranges>
-
-#include <array>
-#include <cassert>
-#include <utility>
-#include "test_iterators.h"
-#include "../types.h"
-
-template <class Iter, class Sent = sentinel_wrapper<Iter>>
-constexpr void test() {
-  using View = minimal_view<Iter, Sent>;
-  using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
-  using FilterIterator = std::ranges::iterator_t<FilterView>;
-
-  std::array<int, 10> array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  View view(Iter(array.data()), Sent(Iter(array.data() + array.size())));
-  Iter iter = view.begin();
-
-  FilterView filter_view(std::move(view), AlwaysTrue{});
-  FilterIterator filter_iter(filter_view, std::move(iter));
-  assert(base(filter_iter.base()) == array.data());
-}
-
-constexpr bool tests() {
-  test<cpp17_input_iterator<int*>>();
-  test<cpp20_input_iterator<int*>>();
-  test<forward_iterator<int*>>();
-  test<bidirectional_iterator<int*>>();
-  test<random_access_iterator<int*>>();
-  test<contiguous_iterator<int*>>();
-  test<int*>();
-  return true;
-}
-
-int main(int, char**) {
-  tests();
-  static_assert(tests());
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
index f4f4982bb9d5d..e794ff133dcb0 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
@@ -36,7 +36,8 @@ constexpr void test() {
   FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
 
   for (std::size_t n = 0; n != array.size(); ++n) {
-    FilterIterator const iter(view, Iter(array.data() + n));
+    FilterIterator iter = view.begin();
+    for (std::size_t i = 0; i < n; ++i) ++iter;
     ValueType& result = *iter;
     ASSERT_SAME_TYPE(ValueType&, decltype(*iter));
     assert(&result == array.data() + n);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp
deleted file mode 100644
index 9896bf80c31e1..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit sentinel(filter_view&);
-
-#include <ranges>
-
-#include <array>
-#include <cassert>
-#include <type_traits>
-#include <utility>
-#include "test_iterators.h"
-#include "../types.h"
-
-template <class Iter, class Sent = sentinel_wrapper<Iter>>
-constexpr void test() {
-  using View = minimal_view<Iter, Sent>;
-  using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
-  using FilterSentinel = std::ranges::sentinel_t<FilterView>;
-
-  auto make_filter_view = [](auto begin, auto end, auto pred) {
-    View view{Iter(begin), Sent(Iter(end))};
-    return FilterView(std::move(view), pred);
-  };
-
-  std::array<int, 5> array{0, 1, 2, 3, 4};
-  FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
-
-  FilterSentinel sent(view);
-  assert(base(base(sent.base())) == base(base(view.end().base())));
-
-  static_assert(!std::is_constructible_v<FilterSentinel, FilterView const&>);
-  static_assert(!std::is_constructible_v<FilterSentinel, FilterView>);
-  static_assert( std::is_constructible_v<FilterSentinel, FilterView&> &&
-                !std::is_convertible_v<FilterView&, FilterSentinel>);
-}
-
-constexpr bool tests() {
-  test<cpp17_input_iterator<int*>>();
-  test<cpp20_input_iterator<int*>>();
-  test<forward_iterator<int*>>();
-  test<bidirectional_iterator<int*>>();
-  test<random_access_iterator<int*>>();
-  test<contiguous_iterator<int*>>();
-  test<int*>();
-  return true;
-}
-
-int main(int, char**) {
-  tests();
-  static_assert(tests());
-  return 0;
-}

>From 11b933048f6a2b6279d2ff8b643ce845975d5efe Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 13:10:28 +0300
Subject: [PATCH 06/28] Tests: `lazy_split_view`

---
 .../ctor.outer_iterator.pass.cpp              | 43 -------------------
 .../ctor.parent.pass.cpp                      | 39 -----------------
 .../ctor.parent_base.pass.cpp                 | 36 ----------------
 3 files changed, 118 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent_base.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.pass.cpp
deleted file mode 100644
index 4981510be52d6..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.pass.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit inner-iterator::inner-iterator(outer-iterator<Const> i);
-
-#include <ranges>
-
-#include "../types.h"
-
-static_assert(!std::is_constructible_v<InnerIterNonConst, OuterIterConst>);
-
-template <class Inner, class Outer>
-constexpr void test_impl() {
-  [[maybe_unused]] Inner i(Outer{});
-  // Verify that the constructor is `explicit`.
-  static_assert(!std::is_convertible_v<Outer, Inner>);
-}
-
-constexpr bool test() {
-  test_impl<InnerIterForward, OuterIterForward>();
-  test_impl<InnerIterInput, OuterIterInput>();
-// Is only constructible if both the outer and the inner iterators have the same constness.
-  test_impl<InnerIterConst, OuterIterConst>();
-// Note: this works because of an implicit conversion (`OuterIterNonConst` is converted to `OuterIterConst`).
-  test_impl<InnerIterConst, OuterIterNonConst>();
-  test_impl<InnerIterNonConst, OuterIterNonConst>();
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.pass.cpp
deleted file mode 100644
index aacf6eabc290a..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.pass.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// explicit std::ranges::lazy_split_view::outer-iterator::outer-iterator(Parent& parent)
-//   requires (!forward_range<Base>)
-
-#include <ranges>
-
-#include <type_traits>
-#include <utility>
-#include "../types.h"
-
-// Verify that the constructor is `explicit`.
-static_assert(!std::is_convertible_v<SplitViewInput&, OuterIterInput>);
-
-static_assert( std::ranges::forward_range<SplitViewForward>);
-static_assert(!std::is_constructible_v<OuterIterForward, SplitViewForward&>);
-
-constexpr bool test() {
-  InputView input;
-  SplitViewInput v(input, ForwardTinyView());
-  [[maybe_unused]] OuterIterInput i(v);
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent_base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent_base.pass.cpp
deleted file mode 100644
index 9fc0ce3748b1f..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent_base.pass.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr outer-iterator(Parent& parent, iterator_t<Base> current);
-//   requires forward_range<Base>
-
-#include <ranges>
-
-#include <type_traits>
-#include <utility>
-#include "../types.h"
-
-static_assert(!std::ranges::forward_range<SplitViewInput>);
-static_assert(!std::is_constructible_v<OuterIterInput, SplitViewInput&, std::ranges::iterator_t<InputView>>);
-
-constexpr bool test() {
-  ForwardView input("abc");
-  SplitViewForward v(std::move(input), " ");
-  [[maybe_unused]] OuterIterForward i(v, input.begin());
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}

>From 74f795f5f559b72803edd152d2f60b772dd697d8 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 13:15:21 +0300
Subject: [PATCH 07/28] Tests: `join_view`

---
 .../range.join.sentinel/ctor.parent.pass.cpp  | 43 -------------------
 1 file changed, 43 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.pass.cpp
deleted file mode 100644
index 1ac68277338fe..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.pass.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit sentinel(Parent& parent);
-
-#include <cassert>
-#include <ranges>
-
-#include "test_macros.h"
-#include "../types.h"
-
-constexpr bool test() {
-  int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
-
-  CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
-  CopyableParent parent{children};
-  std::ranges::join_view jv(parent);
-  std::ranges::sentinel_t<decltype(jv)> sent(jv);
-  assert(sent == std::ranges::next(jv.begin(), 16));
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  {
-    // Test explicitness.
-    using Parent = std::ranges::join_view<ParentView<ChildView>>;
-    static_assert( std::is_constructible_v<std::ranges::sentinel_t<Parent>, Parent&>);
-    static_assert(!std::is_convertible_v<std::ranges::sentinel_t<Parent>, Parent&>);
-  }
-
-  return 0;
-}

>From 3f679ac8813a96d8179f8b72000153c3be0c1f50 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 13:47:11 +0300
Subject: [PATCH 08/28] Tests: `istream_view`

---
 .../range.istream.view/ctor.pass.cpp          |  5 +-
 .../range.istream.view/iterator/ctor.pass.cpp | 58 -------------------
 .../iterator/deref.pass.cpp                   | 10 ----
 3 files changed, 2 insertions(+), 71 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp

diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
index ff60fbff1d73b..beeeea4c1bbe1 100644
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
@@ -39,10 +39,9 @@ void test() {
 
   // LWG 3568. basic_istream_view needs to initialize value_
   {
-    auto iss = make_string_stream<CharT>("123");
+    auto iss = make_string_stream<CharT>("");
     std::ranges::basic_istream_view<int, CharT> isv{iss};
-    using Iter = std::ranges::iterator_t<decltype(isv)>;
-    Iter iter{isv};
+    auto iter = isv.begin();
     assert(*iter == 0);
   }
 }
diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp
deleted file mode 100644
index e180d12924084..0000000000000
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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: no-localization
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// constexpr explicit iterator(basic_istream_view& parent) noexcept;
-
-#include <cassert>
-#include <ranges>
-#include <sstream>
-#include <type_traits>
-
-#include "test_macros.h"
-#include "../utils.h"
-
-// test that the constructor is explicit
-template <class CharT>
-using IstreamView = std::ranges::basic_istream_view<int, CharT>;
-template <class CharT>
-using Iter = std::ranges::iterator_t<IstreamView<CharT>>;
-
-static_assert(std::constructible_from<Iter<char>, IstreamView<char>&>);
-static_assert(!std::convertible_to<IstreamView<char>&, Iter<char>>);
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-static_assert(std::constructible_from<Iter<wchar_t>, IstreamView<wchar_t>&>);
-static_assert(!std::convertible_to<IstreamView<wchar_t>&, Iter<wchar_t>>);
-#endif
-
-// test that the constructor is noexcept
-static_assert(std::is_nothrow_constructible_v<Iter<char>, IstreamView<char>&>);
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-static_assert(std::is_nothrow_constructible_v<Iter<wchar_t>, IstreamView<wchar_t>&>);
-#endif
-
-template <class CharT>
-void test() {
-  auto iss = make_string_stream<CharT>("123");
-  std::ranges::basic_istream_view<int, CharT> isv{iss};
-  Iter<CharT> it{isv};
-  ++it;
-  assert(*it == 123);
-}
-
-int main(int, char**) {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
index 1cf05f0ac4cbe..d010ee06dbf51 100644
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
@@ -29,16 +29,6 @@ void test() {
     assert(v1 == 1);
   }
 
-  // operator* should return the same reference to the value stored in the view
-  {
-    auto iss = make_string_stream<CharT>("1 2 345 ");
-    std::ranges::basic_istream_view<int, CharT> isv{iss};
-    using Iter = std::ranges::iterator_t<decltype(isv)>;
-
-    Iter it1{isv};
-    Iter it2{isv};
-    assert(&*it1 == &*it2);
-  }
 }
 
 int main(int, char**) {

>From 1bd7d694c3339a6b4e16a60a00817dc2130aa312 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 Apr 2026 14:00:32 +0300
Subject: [PATCH 09/28] Tests: `iota_view`

---
 .../iterator/ctor.value.pass.cpp              | 45 ------------------
 .../sentinel/ctor.value.pass.cpp              | 47 -------------------
 2 files changed, 92 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp

diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp
deleted file mode 100644
index a84cb91f7e9b3..0000000000000
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit iterator(W value);
-
-#include <cassert>
-#include <ranges>
-#include <type_traits>
-
-#include "test_macros.h"
-#include "../types.h"
-
-constexpr bool test() {
-  {
-    using Iter = std::ranges::iterator_t<std::ranges::iota_view<int>>;
-    auto iter = Iter(42);
-    assert(*iter == 42);
-  }
-  {
-    using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
-    auto iter = Iter(SomeInt(42));
-    assert(*iter == SomeInt(42));
-  }
-  {
-    using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
-    static_assert(!std::is_convertible_v<Iter, SomeInt>);
-    static_assert( std::is_constructible_v<Iter, SomeInt>);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp
deleted file mode 100644
index a56369b046dc1..0000000000000
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit sentinel(Bound bound);
-
-#include <cassert>
-#include <ranges>
-#include <type_traits>
-
-#include "test_macros.h"
-#include "../types.h"
-
-constexpr bool test() {
-  {
-    using Sent = std::ranges::sentinel_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
-    using Iter = std::ranges::iterator_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
-    auto sent = Sent(IntSentinelWith<int>(42));
-    assert(sent == Iter(42));
-  }
-  {
-    using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
-    using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
-    auto sent = Sent(IntSentinelWith<SomeInt>(SomeInt(42)));
-    assert(sent == Iter(SomeInt(42)));
-  }
-  {
-    using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
-    static_assert(!std::is_convertible_v<Sent, IntSentinelWith<SomeInt>>);
-    static_assert( std::is_constructible_v<Sent, IntSentinelWith<SomeInt>>);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}

>From 5a43b67d99477e25e09d5e2bf471de20bd21ad64 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 11 Apr 2026 14:45:00 +0300
Subject: [PATCH 10/28] Tests: `elements_view`

---
 .../range.elements/iterator/base.pass.cpp     | 12 +++--
 .../iterator/ctor.base.pass.cpp               | 54 -------------------
 .../iterator/ctor.other.pass.cpp              |  8 +--
 .../range.elements/sentinel/base.pass.cpp     |  7 +--
 .../sentinel/ctor.base.pass.cpp               | 52 ------------------
 .../sentinel/ctor.convert.pass.cpp            |  9 ++--
 6 files changed, 20 insertions(+), 122 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index a77e98f845a06..425c13fea707e 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -39,7 +39,7 @@ constexpr bool test() {
 
   // const &
   {
-    const ElementsIter it{&t};
+    const ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = it.base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
@@ -47,7 +47,7 @@ constexpr bool test() {
 
   // &
   {
-    ElementsIter it{&t};
+    ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = it.base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
@@ -55,7 +55,7 @@ constexpr bool test() {
 
   // &&
   {
-    ElementsIter it{&t};
+    ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>*>);
     assert(base == &t);
@@ -63,7 +63,7 @@ constexpr bool test() {
 
   // const &&
   {
-    const ElementsIter it{&t};
+    const ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
@@ -81,7 +81,9 @@ constexpr bool test() {
     using MoveOnlyElemIter =
         std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>;
 
-    MoveOnlyElemIter it{MoveOnlyIter{{}, MoveOnly{5}}};
+    auto it = std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>{
+        std::ranges::subrange{MoveOnlyIter{{}, MoveOnly{5}}, Sent{}}}
+                  .begin();
     decltype(auto) base = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), MoveOnlyIter>);
     assert(base.mo.get() == 5);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp
deleted file mode 100644
index 5a280d294aecc..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit iterator(iterator_t<Base> current);
-
-#include <cassert>
-#include <ranges>
-#include <tuple>
-
-#include "../types.h"
-
-// Test explicit
-using BaseIter     = std::tuple<int>*;
-using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<BaseIter, BaseIter>, 0>>;
-
-static_assert(std::is_constructible_v<ElementsIter, BaseIter>);
-static_assert(!std::is_convertible_v<BaseIter, ElementsIter>);
-
-struct TracedMoveIter : IterBase<TracedMoveIter>{
-  bool moved = false;
-
-  constexpr TracedMoveIter()                      = default;
-  constexpr TracedMoveIter(const TracedMoveIter&) = default;
-  constexpr TracedMoveIter(TracedMoveIter&&) : moved{true} {}
-  constexpr TracedMoveIter& operator=(TracedMoveIter&&)      = default;
-  constexpr TracedMoveIter& operator=(const TracedMoveIter&) = default;
-};
-
-struct TracedMoveView : std::ranges::view_base {
-  TracedMoveIter begin() const;
-  TracedMoveIter end() const;
-};
-
-constexpr bool test() {
-  using Iter = std::ranges::iterator_t<std::ranges::elements_view<TracedMoveView, 0>>;
-  Iter iter{TracedMoveIter{}};
-  assert(iter.base().moved);
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
index 4c94cd5edf62e..d1b8ea73d635d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
@@ -57,10 +57,10 @@ static_assert(!std::is_constructible_v<ConstElemIter<NonConvertibleView>, ElemIt
 static_assert(!std::is_constructible_v<ElemIter<NonConvertibleView>, ConstElemIter<NonConvertibleView>>);
 
 constexpr bool test() {
-  ElemIter<ConvertibleView> iter{ConvertibleIter<false>{5}};
-  ConstElemIter<ConvertibleView> constIter = iter; // implicit
-  assert(constIter.base().movedFromOtherConst);
-  assert(constIter.base().i == 5);
+  // auto iter = std::ranges::elements_view<ConvertibleView, 0>{}.begin();
+  // ConstElemIter<ConvertibleView> constIter = iter; // implicit
+  // assert(constIter.base().movedFromOtherConst);
+  // assert(constIter.base().i == 5);
 
   return true;
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
index d4d0156fdb5be..a11d16817f030 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
@@ -17,7 +17,7 @@
 #include <utility>
 
 struct Sent {
-  int i;
+  int i = 5;
 
   friend constexpr bool operator==(std::tuple<int>*, const Sent&) { return true; }
 };
@@ -27,7 +27,8 @@ constexpr bool test() {
   using EleRange  = std::ranges::elements_view<BaseRange, 0>;
   using EleSent   = std::ranges::sentinel_t<EleRange>;
 
-  const EleSent st{Sent{5}};
+  const EleRange ev;
+  const EleSent st = ev.end();
   std::same_as<Sent> decltype(auto) base = st.base();
   assert(base.i == 5);
 
@@ -36,6 +37,6 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  static_assert(test());
+  // static_assert(test());
   return 0;
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp
deleted file mode 100644
index 13fef1d53f121..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// constexpr explicit sentinel(sentinel_t<Base> end);
-
-#include <cassert>
-#include <ranges>
-#include <tuple>
-#include <utility>
-
-struct Sent {
-  int i;
-
-  friend constexpr bool operator==(std::tuple<int>*, const Sent&) { return true; }
-};
-
-struct Range : std::ranges::view_base {
-  std::tuple<int>* begin() const;
-  Sent end();
-};
-
-// Test explicit
-
-static_assert(std::is_constructible_v<std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>, Sent>);
-static_assert(!std::is_convertible_v<Sent, std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>>);
-
-constexpr bool test() {
-  // base is init correctly
-  {
-    using R        = std::ranges::elements_view<Range, 0>;
-    using Sentinel = std::ranges::sentinel_t<R>;
-
-    Sentinel s1(Sent{5});
-    assert(s1.base().i == 5);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
index a8bc817ced291..ce81d1c00d376 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
@@ -72,9 +72,10 @@ constexpr bool test() {
     using ConstSentinel = std::ranges::sentinel_t<const R>;
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
-    Sentinel s1(Sent{5});
-    ConstSentinel s2 = s1;
-    assert(s2.base().i == 5);
+    // auto s1 = R{}.end();
+    // (void) s1;
+    // ConstSentinel s2 = s1;
+    // assert(s2.base().i == 5);
   }
 
   return true;
@@ -82,7 +83,7 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  static_assert(test());
+  // static_assert(test());
 
   return 0;
 }

>From b4695a242823d5f4943d22cf64802696a092191c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 24 Apr 2026 07:04:24 +0300
Subject: [PATCH 11/28] Format

---
 libcxx/docs/Status/Cxx26Papers.csv                |  2 +-
 .../range.elements/iterator/base.pass.cpp         | 15 ++++++++-------
 .../range.elements/sentinel/base.pass.cpp         |  2 +-
 .../range.split/iterator/base.pass.cpp            | 10 +++++-----
 .../range.split/iterator/deref.pass.cpp           |  7 +++----
 .../sentinel/ctor.convert.pass.cpp                |  4 ++--
 6 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index 7fcebd331197b..ffa36d3f5145c 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -188,7 +188,7 @@
 "`P4140R0 <https://wg21.link/P4140R0>`__","Proposed resolution for US70-126: allow incomplete types in type_order","2026-03 (Croydon)","","","`#189595 <https://github.com/llvm/llvm-project/issues/189595>`__",""
 "`P3373R4 <https://wg21.link/P3373R4>`__","Of Operation States and Their Lifetimes","2026-03 (Croydon)","","","`#189597 <https://github.com/llvm/llvm-project/issues/189597>`__",""
 "`P3986R1 <https://wg21.link/P3986R1>`__","A Wording Strategy for Inlinable Receivers","2026-03 (Croydon)","","","`#189598 <https://github.com/llvm/llvm-project/issues/189598>`__",""
-"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","","","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
+"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","|Complete|","23","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
 "`P3725R3 <https://wg21.link/P3725R3>`__","Filter View Extensions for Safer Use, Rev 3","2026-03 (Croydon)","","","`#189601 <https://github.com/llvm/llvm-project/issues/189601>`__",""
 "`P3828R1 <https://wg21.link/P3828R1>`__","Rename the to_input view to as_input","2026-03 (Croydon)","","","`#189602 <https://github.com/llvm/llvm-project/issues/189602>`__",""
 "`P3795R2 <https://wg21.link/P3795R2>`__","Miscellaneous Reflection Cleanup","2026-03 (Croydon)","","","`#189603 <https://github.com/llvm/llvm-project/issues/189603>`__",""
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index 425c13fea707e..316e3523edc73 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -40,14 +40,14 @@ constexpr bool test() {
   // const &
   {
     const ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
-    decltype(auto) base = it.base();
+    decltype(auto) base   = it.base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
   }
 
   // &
   {
-    ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
+    ElementsIter it     = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = it.base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
@@ -55,7 +55,7 @@ constexpr bool test() {
 
   // &&
   {
-    ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
+    ElementsIter it     = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
     decltype(auto) base = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>*>);
     assert(base == &t);
@@ -64,7 +64,7 @@ constexpr bool test() {
   // const &&
   {
     const ElementsIter it = std::ranges::elements_view<BaseView, 0>{BaseView{&t, &t + 1}}.begin();
-    decltype(auto) base = std::move(it).base();
+    decltype(auto) base   = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
     assert(base == &t);
   }
@@ -81,9 +81,10 @@ constexpr bool test() {
     using MoveOnlyElemIter =
         std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>;
 
-    auto it = std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>{
-        std::ranges::subrange{MoveOnlyIter{{}, MoveOnly{5}}, Sent{}}}
-                  .begin();
+    auto it =
+        std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>{
+            std::ranges::subrange{MoveOnlyIter{{}, MoveOnly{5}}, Sent{}}}
+            .begin();
     decltype(auto) base = std::move(it).base();
     static_assert(std::is_same_v<decltype(base), MoveOnlyIter>);
     assert(base.mo.get() == 5);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
index a11d16817f030..885582a5c94a8 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
@@ -28,7 +28,7 @@ constexpr bool test() {
   using EleSent   = std::ranges::sentinel_t<EleRange>;
 
   const EleRange ev;
-  const EleSent st = ev.end();
+  const EleSent st                       = ev.end();
   std::same_as<Sent> decltype(auto) base = st.base();
   assert(base.i == 5);
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
index 66c2914ba1919..fe9be0e97104c 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
@@ -16,7 +16,7 @@
 #include "../types.h"
 
 struct Iter : ForwardIterBase<Iter> {
-  int i = 0;
+  int i            = 0;
   constexpr Iter() = default;
   constexpr Iter(int ii) : i(ii) {}
   constexpr int operator*() const { return i; }
@@ -42,28 +42,28 @@ constexpr bool test() {
 
   // const &
   {
-    const SplitIter it = sv.begin();
+    const SplitIter it                     = sv.begin();
     std::same_as<Iter> decltype(auto) base = it.base();
     assert(base.i == 5);
   }
 
   // &
   {
-    SplitIter it = sv.begin();
+    SplitIter it                           = sv.begin();
     std::same_as<Iter> decltype(auto) base = it.base();
     assert(base.i == 5);
   }
 
   // &&
   {
-    SplitIter it = sv.begin();
+    SplitIter it                           = sv.begin();
     std::same_as<Iter> decltype(auto) base = std::move(it).base();
     assert(base.i == 5);
   }
 
   // const &&
   {
-    const SplitIter it = sv.begin();
+    const SplitIter it                     = sv.begin();
     std::same_as<Iter> decltype(auto) base = std::move(it).base();
     assert(base.i == 5);
   }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
index be7aca854f640..0e9812020fb38 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/deref.pass.cpp
@@ -17,7 +17,7 @@
 #include "../types.h"
 
 struct Iter : ForwardIterBase<Iter> {
-  int i = 0;
+  int i            = 0;
   constexpr Iter() = default;
   constexpr Iter(int ii) : i(ii) {}
   constexpr int operator*() const { return i; }
@@ -37,9 +37,8 @@ constexpr bool test() {
   using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
   using SplitIter = std::ranges::iterator_t<SplitView>;
 
-  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}},
-               std::ranges::subrange<Iter>{Iter{7}, Iter{8}}};
-  const SplitIter it = sv.begin();
+  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}}, std::ranges::subrange<Iter>{Iter{7}, Iter{8}}};
+  const SplitIter it                                             = sv.begin();
   std::same_as<std::ranges::subrange<Iter>> decltype(auto) value = *it;
   assert(value.begin().i == 5);
   assert(value.end().i == 7);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
index 0fffe9b508816..8a9ee79660a1d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
@@ -107,7 +107,7 @@ constexpr bool test() {
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
     R r{TestRng{}, pred};
-    Sentinel s1 = r.end();
+    Sentinel s1      = r.end();
     ConstSentinel s2 = s1;
 
     int i     = 10;
@@ -141,7 +141,7 @@ constexpr bool test() {
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
     R r{Rng{}, TestPred{}};
-    Sentinel s1 = r.end();
+    Sentinel s1      = r.end();
     ConstSentinel s2 = s1;
     assert(s2.base().i == 0);
   }

>From ee7863618f3b2d5bc4fc88409b2d77d0424444ec Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 17 Jul 2026 21:28:20 +0300
Subject: [PATCH 12/28] Release notes

---
 libcxx/docs/ReleaseNotes/24.rst    | 1 +
 libcxx/docs/Status/Cxx26Papers.csv | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index 70c704ff9d326..052e5eab25433 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -39,6 +39,7 @@ Implemented Papers
 ------------------
 
 - P0493R5: Atomic minimum/maximum (`Github <https://llvm.org/PR105418>`__)
+- P3059R2: Making user-defined constructors of view iterators/sentinels private (`Github <https://github.com/llvm/llvm-project/issues/189599>`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index ffa36d3f5145c..4d0fbca940b92 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -188,7 +188,7 @@
 "`P4140R0 <https://wg21.link/P4140R0>`__","Proposed resolution for US70-126: allow incomplete types in type_order","2026-03 (Croydon)","","","`#189595 <https://github.com/llvm/llvm-project/issues/189595>`__",""
 "`P3373R4 <https://wg21.link/P3373R4>`__","Of Operation States and Their Lifetimes","2026-03 (Croydon)","","","`#189597 <https://github.com/llvm/llvm-project/issues/189597>`__",""
 "`P3986R1 <https://wg21.link/P3986R1>`__","A Wording Strategy for Inlinable Receivers","2026-03 (Croydon)","","","`#189598 <https://github.com/llvm/llvm-project/issues/189598>`__",""
-"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","|Complete|","23","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
+"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","|Complete|","24","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
 "`P3725R3 <https://wg21.link/P3725R3>`__","Filter View Extensions for Safer Use, Rev 3","2026-03 (Croydon)","","","`#189601 <https://github.com/llvm/llvm-project/issues/189601>`__",""
 "`P3828R1 <https://wg21.link/P3828R1>`__","Rename the to_input view to as_input","2026-03 (Croydon)","","","`#189602 <https://github.com/llvm/llvm-project/issues/189602>`__",""
 "`P3795R2 <https://wg21.link/P3795R2>`__","Miscellaneous Reflection Cleanup","2026-03 (Croydon)","","","`#189603 <https://github.com/llvm/llvm-project/issues/189603>`__",""

>From 11b36027bc4737a06ac1368d0c4027bead46a6c4 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 17 Jul 2026 21:42:44 +0300
Subject: [PATCH 13/28] Format

---
 .../range.adaptors/range.filter/iterator/arrow.pass.cpp     | 3 ++-
 .../range.adaptors/range.filter/iterator/deref.pass.cpp     | 3 ++-
 .../range.adaptors/range.split/iterator/base.pass.cpp       | 3 +--
 .../range.take.while/sentinel/ctor.convert.pass.cpp         | 6 +++---
 .../range.istream.view/iterator/deref.pass.cpp              | 1 -
 5 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
index 46d59c3de1d7d..284a22d218bf0 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/arrow.pass.cpp
@@ -88,7 +88,8 @@ constexpr void test() {
   for (std::ptrdiff_t n = 0; n != 5; ++n) {
     FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
     FilterIterator iter = view.begin();
-    for (std::ptrdiff_t i = 0; i < n; ++i) ++iter;
+    for (std::ptrdiff_t i = 0; i < n; ++i)
+      ++iter;
     std::same_as<Iter> decltype(auto) result = iter.operator->();
     assert(base(result) == array.data() + n);
     assert(iter->x == n);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
index e794ff133dcb0..42b0f1816d8a1 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp
@@ -37,7 +37,8 @@ constexpr void test() {
 
   for (std::size_t n = 0; n != array.size(); ++n) {
     FilterIterator iter = view.begin();
-    for (std::size_t i = 0; i < n; ++i) ++iter;
+    for (std::size_t i = 0; i < n; ++i)
+      ++iter;
     ValueType& result = *iter;
     ASSERT_SAME_TYPE(ValueType&, decltype(*iter));
     assert(&result == array.data() + n);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
index fe9be0e97104c..8e8eff8a12b97 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/base.pass.cpp
@@ -37,8 +37,7 @@ constexpr bool test() {
   using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
   using SplitIter = std::ranges::iterator_t<SplitView>;
 
-  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}},
-               std::ranges::subrange<Iter>{Iter{8}, Iter{9}}};
+  SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}}, std::ranges::subrange<Iter>{Iter{8}, Iter{9}}};
 
   // const &
   {
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
index 8a9ee79660a1d..1808545422498 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.convert.pass.cpp
@@ -82,7 +82,7 @@ constexpr bool test() {
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
     R r{TestRng{}, nullptr};
-    Sentinel s1 = r.end();
+    Sentinel s1      = r.end();
     ConstSentinel s2 = s1;
     assert(s2.base().i == 5);
   }
@@ -110,8 +110,8 @@ constexpr bool test() {
     Sentinel s1      = r.end();
     ConstSentinel s2 = s1;
 
-    int i     = 10;
-    int* iter = &i;
+    int i                   = 10;
+    int* iter               = &i;
     [[maybe_unused]] bool b = iter == s2;
     assert(called);
   }
diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
index d010ee06dbf51..9f9f13399392c 100644
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
@@ -28,7 +28,6 @@ void test() {
     std::same_as<int&> decltype(auto) v1 = *it;
     assert(v1 == 1);
   }
-
 }
 
 int main(int, char**) {

>From 4127ad1211b268ab699b7c84aa543f8ce99fdc90 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 20 Jul 2026 14:02:29 +0300
Subject: [PATCH 14/28] Tests: `elements_view` updates

---
 .../iterator/ctor.other.pass.cpp               | 16 ++++++++++++----
 .../sentinel/ctor.convert.pass.cpp             | 18 ++++++++++++------
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
index d1b8ea73d635d..9255fb47013b6 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp
@@ -57,10 +57,18 @@ static_assert(!std::is_constructible_v<ConstElemIter<NonConvertibleView>, ElemIt
 static_assert(!std::is_constructible_v<ElemIter<NonConvertibleView>, ConstElemIter<NonConvertibleView>>);
 
 constexpr bool test() {
-  // auto iter = std::ranges::elements_view<ConvertibleView, 0>{}.begin();
-  // ConstElemIter<ConvertibleView> constIter = iter; // implicit
-  // assert(constIter.base().movedFromOtherConst);
-  // assert(constIter.base().i == 5);
+  struct TestRange : std::ranges::view_base {
+    constexpr ConvertibleIter<false> begin() { return ConvertibleIter<false>{5}; }
+    constexpr ConvertibleIter<false> end() { return ConvertibleIter<false>{5}; }
+    constexpr ConvertibleIter<true> begin() const { return ConvertibleIter<true>{5}; }
+    constexpr ConvertibleIter<true> end() const { return ConvertibleIter<true>{5}; }
+  };
+
+  std::ranges::elements_view<TestRange, 0> ev{TestRange{}};
+  ElemIter<TestRange> iter           = ev.begin();
+  ConstElemIter<TestRange> constIter = iter; // implicit
+  assert(constIter.base().movedFromOtherConst);
+  assert(constIter.base().i == 5);
 
   return true;
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
index ce81d1c00d376..25d1413b2fa16 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp
@@ -67,15 +67,21 @@ static_assert(
 constexpr bool test() {
   // base is init correctly
   {
-    using R             = std::ranges::elements_view<Range, 0>;
+    struct TestRange : std::ranges::view_base {
+      constexpr std::tuple<int>* begin() const { return nullptr; }
+      constexpr Sent end() { return Sent{5}; }
+      constexpr ConstSent end() const { return ConstSent{5}; }
+    };
+
+    using R             = std::ranges::elements_view<TestRange, 0>;
     using Sentinel      = std::ranges::sentinel_t<R>;
     using ConstSentinel = std::ranges::sentinel_t<const R>;
     static_assert(!std::same_as<Sentinel, ConstSentinel>);
 
-    // auto s1 = R{}.end();
-    // (void) s1;
-    // ConstSentinel s2 = s1;
-    // assert(s2.base().i == 5);
+    R r{TestRange{}};
+    Sentinel s1      = r.end();
+    ConstSentinel s2 = s1;
+    assert(s2.base().i == 5);
   }
 
   return true;
@@ -83,7 +89,7 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  // static_assert(test());
+  static_assert(test());
 
   return 0;
 }

>From c33bac978f0ecf59b457c38f5a12c79c56af2fac Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 20 Jul 2026 14:03:34 +0300
Subject: [PATCH 15/28] Revert formatting

---
 .../range.adaptors/range.elements/iterator/base.pass.cpp       | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index 316e3523edc73..27801eadac30f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -22,7 +22,8 @@
 
 // Test Noexcept
 template <class T>
-concept IsBaseNoexcept = requires {
+concept IsBaseNoexcept =
+    requires {
   { std::declval<T>().base() } noexcept;
 };
 

>From e35c0d0bed0d974cacdc104648177102db7dedbe Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Mon, 20 Jul 2026 15:24:00 +0300
Subject: [PATCH 16/28] Apply suggestion from @frederick-vs-ja

Co-authored-by: A. Jiang <de34 at live.cn>
---
 .../range.adaptors/range.elements/iterator/base.pass.cpp       | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index 27801eadac30f..e28c36b1254af 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -79,9 +79,6 @@ constexpr bool test() {
       constexpr bool operator==(const MoveOnlyIter&) const { return true; }
     };
 
-    using MoveOnlyElemIter =
-        std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>;
-
     auto it =
         std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>{
             std::ranges::subrange{MoveOnlyIter{{}, MoveOnly{5}}, Sent{}}}

>From dc161708c53ce4ecf0b5596956eec6f7b03cfe36 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 21 Jul 2026 00:05:55 +0300
Subject: [PATCH 17/28] Fixed formatting

---
 .../range.adaptors/range.elements/iterator/base.pass.cpp       | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index e28c36b1254af..bcce8e1f48f7b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -22,8 +22,7 @@
 
 // Test Noexcept
 template <class T>
-concept IsBaseNoexcept =
-    requires {
+concept IsBaseNoexcept = requires {
   { std::declval<T>().base() } noexcept;
 };
 

>From f4d45145cd5092bb65a8137a243dc94a8e107812 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 21 Jul 2026 00:18:55 +0300
Subject: [PATCH 18/28] Enable test

---
 .../ranges/range.adaptors/range.elements/sentinel/base.pass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
index 885582a5c94a8..114b7fc1f1b71 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp
@@ -37,6 +37,6 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  // static_assert(test());
+  static_assert(test());
   return 0;
 }

>From 851f503a96a63350ca8f809a8c5deca584405d68 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 21 Jul 2026 07:53:40 +0300
Subject: [PATCH 19/28] Added `std::is_constructible/convertible` tests

---
 .../iterator/ctor.base.compile.pass.cpp       | 23 ++++++++++++
 .../sentinel/ctor.base.compile.pass.cpp       | 30 ++++++++++++++++
 .../ctor.parent.iter.compile.pass.cpp         | 25 +++++++++++++
 .../sentinel/ctor.parent.compile.pass.cpp     | 25 +++++++++++++
 .../ctor.outer_iterator.compile.pass.cpp      | 23 ++++++++++++
 .../ctor.parent.base.compile.pass.cpp         | 22 ++++++++++++
 .../ctor.parent.compile.pass.cpp              | 23 ++++++++++++
 .../sentinel/ctor.base.pred.compile.pass.cpp  | 35 +++++++++++++++++++
 .../iterator/ctor.value.compile.pass.cpp      | 26 ++++++++++++++
 .../sentinel/ctor.value.compile.pass.cpp      | 24 +++++++++++++
 .../iterator/ctor.parent.compile.pass.cpp     | 33 +++++++++++++++++
 11 files changed, 289 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.base.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pred.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.compile.pass.cpp
new file mode 100644
index 0000000000000..b43a60276e280
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit iterator(iterator_t<Base> current);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <tuple>
+#include <type_traits>
+
+using BaseIter     = std::tuple<int>*;
+using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<BaseIter, BaseIter>, 0>>;
+
+static_assert(!std::is_constructible_v<ElementsIter, BaseIter>);
+static_assert(!std::is_convertible_v<BaseIter, ElementsIter>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.compile.pass.cpp
new file mode 100644
index 0000000000000..ee4a297c1f4a9
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.compile.pass.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(sentinel_t<Base> end);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+struct Sent {
+  int i;
+
+  friend constexpr bool operator==(std::tuple<int>*, const Sent&) { return true; }
+};
+
+struct Range : std::ranges::view_base {
+  std::tuple<int>* begin() const;
+  Sent end();
+};
+
+static_assert(!std::is_constructible_v<std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>, Sent>);
+static_assert(!std::is_convertible_v<Sent, std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
new file mode 100644
index 0000000000000..4a013d0072222
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr std::ranges::filter_view::<iterator>(filter_view&, iterator_t<V>);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "test_iterators.h"
+#include "../types.h"
+
+using View           = minimal_view<int*, sentinel_wrapper<int*>>;
+using FilterView     = std::ranges::filter_view<View, AlwaysTrue>;
+using FilterIterator = std::ranges::iterator_t<FilterView>;
+
+static_assert(!std::constructible_from<FilterIterator, FilterView>);
+static_assert(!std::convertible_to<FilterView, FilterIterator>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.compile.pass.cpp
new file mode 100644
index 0000000000000..06e06aeb6db6e
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(filter_view&);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "test_iterators.h"
+#include "../types.h"
+
+using View           = minimal_view<int*, sentinel_wrapper<int*>>;
+using FilterView     = std::ranges::filter_view<View, AlwaysTrue>;
+using FilterSentinel = std::ranges::sentinel_t<FilterView>;
+
+static_assert(!std::constructible_from<FilterSentinel, FilterView>);
+static_assert(!std::convertible_to<FilterView, FilterSentinel>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.compile.pass.cpp
new file mode 100644
index 0000000000000..37fe2fadfd41a
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.inner/ctor.outer_iterator.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit inner-iterator::inner-iterator(outer-iterator<Const> i);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "../types.h"
+
+static_assert(!std::is_constructible_v<InnerIterConst, OuterIterConst>);
+static_assert(!std::is_convertible_v<InnerIterConst, OuterIterConst>);
+
+static_assert(!std::is_constructible_v<InnerIterNonConst, OuterIterNonConst>);
+static_assert(!std::is_convertible_v<InnerIterNonConst, OuterIterNonConst>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.base.compile.pass.cpp
new file mode 100644
index 0000000000000..70e97ea04f5c0
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.base.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr outer-iterator(Parent& parent, iterator_t<Base> current);
+//   requires forward_range<Base>
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+#include "../types.h"
+
+static_assert(std::ranges::forward_range<SplitViewForward>);
+static_assert(!std::is_constructible_v<OuterIterForward, SplitViewForward&, std::ranges::iterator_t<ForwardView>>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.compile.pass.cpp
new file mode 100644
index 0000000000000..b838970718c8a
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer/ctor.parent.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// explicit std::ranges::lazy_split_view::outer-iterator::outer-iterator(Parent& parent)
+//   requires (!forward_range<Base>)
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+#include "../types.h"
+
+static_assert(!std::ranges::forward_range<SplitViewInput>);
+static_assert(!std::is_constructible_v<OuterIterInput, SplitViewInput&>);
+static_assert(!std::is_convertible_v<SplitViewInput&, OuterIterInput>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pred.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pred.compile.pass.cpp
new file mode 100644
index 0000000000000..a66e3d1e84c6e
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/ctor.base.pred.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+struct Sent {
+  int i;
+
+  friend constexpr bool operator==(int* iter, const Sent& s) { return s.i > *iter; }
+};
+
+struct Range : std::ranges::view_base {
+  int* begin() const;
+  Sent end();
+};
+
+struct Pred {
+  bool operator()(int i) const;
+};
+
+using Sentinel = std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>;
+
+static_assert(!std::is_constructible_v<Sentinel, std::ranges::sentinel_t<Range>, const Pred*>);
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp
new file mode 100644
index 0000000000000..e95042e26e146
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit iterator(W value);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../types.h"
+
+static_assert(!std::is_constructible_v<std::ranges::iterator_t<std::ranges::iota_view<int>>, int>);
+
+using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
+static_assert(!std::is_constructible_v<Iter, SomeInt>);
+static_assert(!std::is_convertible_v<SomeInt, Iter>);
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp
new file mode 100644
index 0000000000000..a39efb4318794
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(Bound bound);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../types.h"
+
+using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
+static_assert(!std::is_constructible_v<Sent, IntSentinelWith<SomeInt>>);
+static_assert(!std::is_convertible_v<IntSentinelWith<SomeInt>, Sent>);
diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp
new file mode 100644
index 0000000000000..171e2dce1e5f0
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit iterator(basic_istream_view& parent) noexcept;
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <sstream>
+#include <type_traits>
+
+#include "test_macros.h"
+
+// test that the constructor is explicit
+template <class CharT>
+using IstreamView = std::ranges::basic_istream_view<int, CharT>;
+template <class CharT>
+using Iter = std::ranges::iterator_t<IstreamView<CharT>>;
+
+static_assert(!std::constructible_from<Iter<char>, IstreamView<char>&>);
+static_assert(!std::convertible_to<IstreamView<char>&, Iter<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!std::constructible_from<Iter<wchar_t>, IstreamView<wchar_t>&>);
+static_assert(!std::convertible_to<IstreamView<wchar_t>&, Iter<wchar_t>>);
+#endif

>From cfa8219f33f0d433afaa3144d3183bd763d58854 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 09:20:54 +0300
Subject: [PATCH 20/28] Cleanup

---
 .../range.iota.view/iterator/ctor.value.compile.pass.cpp        | 2 --
 .../range.iota.view/sentinel/ctor.value.compile.pass.cpp        | 2 --
 2 files changed, 4 deletions(-)

diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp
index e95042e26e146..fc3384e191d1d 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.compile.pass.cpp
@@ -15,8 +15,6 @@
 #include <ranges>
 #include <type_traits>
 
-#include "test_macros.h"
-
 #include "../types.h"
 
 static_assert(!std::is_constructible_v<std::ranges::iterator_t<std::ranges::iota_view<int>>, int>);
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp
index a39efb4318794..b0bcdb6c60ce7 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.compile.pass.cpp
@@ -15,8 +15,6 @@
 #include <ranges>
 #include <type_traits>
 
-#include "test_macros.h"
-
 #include "../types.h"
 
 using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;

>From 1438ff9824d09adb014641acc0ae3b0775ea8d27 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 10:42:42 +0300
Subject: [PATCH 21/28] Fixed CI

---
 .../range.istream.view/iterator/ctor.parent.compile.pass.cpp     | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp
index 171e2dce1e5f0..04ff9ac24d731 100644
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.parent.compile.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // REQUIRES: std-at-least-c++20
+// UNSUPPORTED: no-localization
 
 // constexpr explicit iterator(basic_istream_view& parent) noexcept;
 

>From 98ad281967c925d3cbc27adaeabafeaddddd2227 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 10:57:29 +0300
Subject: [PATCH 22/28] Restored a test case!

---
 .../range.istream.view/iterator/deref.pass.cpp        | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
index 9f9f13399392c..5df730410a4ad 100644
--- a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
@@ -28,6 +28,17 @@ void test() {
     std::same_as<int&> decltype(auto) v1 = *it;
     assert(v1 == 1);
   }
+
+  // operator* should return the same reference to the value stored in the view
+  {
+    auto iss = make_string_stream<CharT>("1 2 345 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    using Iter = std::ranges::iterator_t<decltype(isv)>;
+
+    Iter it1 = isv.begin();
+    Iter it2 = isv.begin();
+    assert(&*it1 == &*it2);
+  }
 }
 
 int main(int, char**) {

>From ea4f9412bc9b26b3ae55b40c23ee1ac615bbb643 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 11:16:34 +0300
Subject: [PATCH 23/28] Added a missing `take_view` test

---
 .../ctor.base.compile.pass.cpp                | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.base.compile.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.base.compile.pass.cpp
new file mode 100644
index 0000000000000..9383508165609
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.take/range.take.sentinel/ctor.base.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(sentinel_t<Base> end);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+#include <type_traits>
+
+#include "test_iterators.h"
+#include "../types.h"
+
+using TakeView = std::ranges::take_view<MoveOnlyView>;
+using Sentinel = std::ranges::sentinel_t<TakeView>;
+
+static_assert(!std::is_constructible_v<Sentinel, sentinel_wrapper<int*>>);
+static_assert(!std::is_convertible_v<sentinel_wrapper<int*>, Sentinel>);

>From d0afec965397496a91848fdd2e46ed89c98e7039 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 11:34:21 +0300
Subject: [PATCH 24/28] Added missing test `join_view`

---
 .../ctor.parent.compile.pass.cpp              | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.compile.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.compile.pass.cpp
new file mode 100644
index 0000000000000..504c945e3d918
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.parent.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(Parent& parent);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "../types.h"
+
+using Parent = std::ranges::join_view<ParentView<ChildView>>;
+static_assert(!std::is_constructible_v<std::ranges::sentinel_t<Parent>, Parent&>);
+static_assert(!std::is_convertible_v<std::ranges::sentinel_t<Parent>, Parent&>);

>From c50248da199d6cbb3d5ba6b292ef102e7e960d30 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 11:54:39 +0300
Subject: [PATCH 25/28] Update tests `split_view`

---
 ...tor.parent.iter.subrange.compile.pass.cpp} | 31 +++++------------
 ....pass.cpp => ctor.parent.compile.pass.cpp} | 34 ++++---------------
 2 files changed, 14 insertions(+), 51 deletions(-)
 rename libcxx/test/std/ranges/range.adaptors/range.split/iterator/{ctor.base.pass.cpp => ctor.parent.iter.subrange.compile.pass.cpp} (64%)
 rename libcxx/test/std/ranges/range.adaptors/range.split/sentinel/{ctor.parent.pass.cpp => ctor.parent.compile.pass.cpp} (57%)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.parent.iter.subrange.compile.pass.cpp
similarity index 64%
rename from libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp
rename to libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.parent.iter.subrange.compile.pass.cpp
index 823e22e117f77..9f4e9a13e0447 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/iterator/ctor.parent.iter.subrange.compile.pass.cpp
@@ -6,12 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++20
 
-// constexpr iterator begin();
+// constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
 
-#include <cassert>
 #include <ranges>
+#include <type_traits>
 
 #include "../types.h"
 
@@ -30,24 +32,7 @@ struct TracedMoveView : std::ranges::view_base {
   constexpr TracedMoveIter end() const { return {}; }
 };
 
-constexpr bool test() {
-  using SplitView = std::ranges::split_view<TracedMoveView, TracedMoveView>;
-  using SplitIter = std::ranges::iterator_t<SplitView>;
-
-  SplitView sv{TracedMoveView{}, TracedMoveView{}};
-  SplitIter iter = sv.begin();
-  assert(iter.base().moved);
-
-  auto subRange = *iter;
-  assert(subRange.begin().moved);
-  assert(subRange.end().moved);
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
+using SplitView = std::ranges::split_view<TracedMoveView, TracedMoveView>;
+using SplitIter = std::ranges::iterator_t<SplitView>;
 
-  return 0;
-}
+static_assert(!std::is_constructible_v<SplitIter, SplitView, TracedMoveIter, std::ranges::subrange<TracedMoveIter>>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
similarity index 57%
rename from libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp
rename to libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
index 6e1ba912a201b..85d7e908a057c 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
@@ -6,41 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++20
 
 // constexpr explicit sentinel(split_view& parent);
 
-#include <cassert>
+// The constructor is now `private` (exposition-only) per P3059R2.
+
 #include <ranges>
-#include <type_traits>
 
-#include "test_iterators.h"
+#include "../types.h"
 
-// test explicit
 using Range     = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
 using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
 using SplitSent = std::ranges::sentinel_t<SplitView>;
 
-constexpr bool test() {
-  {
-    int buffer[] = {0, 1, 2};
-    Range input{buffer, sentinel_wrapper<int*>(buffer + 3)};
-    SplitView sv(input, -1);
-    auto it = sv.begin();
-
-    auto sent = sv.end();
-    assert(sent != it);
-
-    ++it;
-    assert(sent == it);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
+static_assert(std::is_constructible_v<SplitSent, SplitView&>);
+static_assert(!std::is_convertible_v<SplitView&, SplitSent>);

>From 50dc3e4c1aa67aa0e1b582eeecfbc904d7c80ef1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 11:57:06 +0300
Subject: [PATCH 26/28] Fixed test

---
 .../range.split/sentinel/ctor.parent.compile.pass.cpp           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
index 85d7e908a057c..e0e8029c4c538 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/sentinel/ctor.parent.compile.pass.cpp
@@ -20,5 +20,5 @@ using Range     = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
 using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
 using SplitSent = std::ranges::sentinel_t<SplitView>;
 
-static_assert(std::is_constructible_v<SplitSent, SplitView&>);
+static_assert(!std::is_constructible_v<SplitSent, SplitView&>);
 static_assert(!std::is_convertible_v<SplitView&, SplitSent>);

>From d93fdef4663517663ff4169230e6b2333f637d6e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 12:49:06 +0300
Subject: [PATCH 27/28] Added missing `transform_view` tests

---
 .../ctor.parent.iter.compile.pass.cpp         | 23 ++++++++++++++++++
 .../sentinel/ctor.base.compile.pass.cpp       | 24 +++++++++++++++++++
 .../{iterator => sentinel}/sentinel.pass.cpp  |  0
 3 files changed, 47 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.transform/iterator/ctor.parent.iter.compile.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp
 rename libcxx/test/std/ranges/range.adaptors/range.transform/{iterator => sentinel}/sentinel.pass.cpp (100%)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/ctor.parent.iter.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/ctor.parent.iter.compile.pass.cpp
new file mode 100644
index 0000000000000..e7841dede5bc2
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/ctor.parent.iter.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+//  constexpr iterator(Parent& parent, iterator_t<Base> current);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "../types.h"
+
+using TransformView = std::ranges::transform_view<MoveOnlyView, PlusOne>;
+using TransformViewBaseIter =  std::ranges::iterator_t<MoveOnlyView>;
+using TransformIter = std::ranges::iterator_t<TransformView>;
+
+static_assert(!std::is_constructible_v<TransformIter, TransformView, TransformViewBaseIter>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp
new file mode 100644
index 0000000000000..08be4bbd16667
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// constexpr explicit sentinel(sentinel_t<Base> end);
+
+// The constructor is now `private` (exposition-only) per P3059R2.
+
+#include <ranges>
+
+#include "../types.h"
+
+using Range     = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
+using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
+using SplitSent = std::ranges::sentinel_t<SplitView>;
+
+static_assert(!std::is_constructible_v<SplitSent, SplitView&>);
+static_assert(!std::is_convertible_v<SplitView&, SplitSent>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/sentinel.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/sentinel.pass.cpp
similarity index 100%
rename from libcxx/test/std/ranges/range.adaptors/range.transform/iterator/sentinel.pass.cpp
rename to libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/sentinel.pass.cpp

>From 2b952f73eb09938ae7065c16560692152e4f0c50 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 22 Jul 2026 13:32:08 +0300
Subject: [PATCH 28/28] Try to fix the tests

---
 .../iterator/ctor.parent.iter.compile.pass.cpp           | 3 ++-
 .../range.transform/sentinel/ctor.base.compile.pass.cpp  | 9 +++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
index 4a013d0072222..bca1b3bda4b24 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/iterator/ctor.parent.iter.compile.pass.cpp
@@ -18,8 +18,9 @@
 #include "../types.h"
 
 using View           = minimal_view<int*, sentinel_wrapper<int*>>;
+using ViewIter       = std::ranges::iterator_t<View>;
 using FilterView     = std::ranges::filter_view<View, AlwaysTrue>;
 using FilterIterator = std::ranges::iterator_t<FilterView>;
 
-static_assert(!std::constructible_from<FilterIterator, FilterView>);
+static_assert(!std::constructible_from<FilterIterator, FilterView, ViewIter>);
 static_assert(!std::convertible_to<FilterView, FilterIterator>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp
index 08be4bbd16667..25a73252bcd2e 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/sentinel/ctor.base.compile.pass.cpp
@@ -14,11 +14,12 @@
 
 #include <ranges>
 
-#include "../types.h"
-
+#include "test_iterators.h"
+                                                                    
 using Range     = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
+using RangeSent = std::ranges::sentinel_t<Range>;
 using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
 using SplitSent = std::ranges::sentinel_t<SplitView>;
 
-static_assert(!std::is_constructible_v<SplitSent, SplitView&>);
-static_assert(!std::is_convertible_v<SplitView&, SplitSent>);
+static_assert(!std::is_constructible_v<SplitSent, RangeSent>);
+static_assert(!std::is_convertible_v<RangeSent, SplitSent>);



More information about the libcxx-commits mailing list