[libcxx-commits] [libcxx] 21f78d9 - [libc++][ranges] Fix the LWG 3568 test for `basic_istream_view` (#215589)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 13 03:32:38 PDT 2026


Author: Iskandar Emomzoda
Date: 2026-08-13T18:32:32+08:00
New Revision: 21f78d9c5dd6c92464093facae4c24a52a0fd846

URL: https://github.com/llvm/llvm-project/commit/21f78d9c5dd6c92464093facae4c24a52a0fd846
DIFF: https://github.com/llvm/llvm-project/commit/21f78d9c5dd6c92464093facae4c24a52a0fd846.diff

LOG: [libc++][ranges] Fix the LWG 3568 test for `basic_istream_view` (#215589)

The previous test was dereferencing `begin()` iterator on empty view
which is UB, because `begin() == end()`.

A new test case was suggested in a post-merge feedback in #193891, which
verifies LWG3568 through constant evaluation. Such a `constexpr`
`basic_istream_view` variable can only be created if it is completely
initialized, including its exposition-only _`value_`_ member.

The existing test case is changed to use a non-empty stream and a
testing class type for which `operator>>` is no-op. The state of the
class object stored in `basic_istream_view` is unchanged even after the
initial `operator>>` call.

This avoids dereferencing a past-the-end iterator while testing LWG3568.

Added: 
    

Modified: 
    libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp

Removed: 
    


################################################################################
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 beeeea4c1bbe1..7e9ec8bf631a8 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
@@ -27,6 +27,15 @@ static_assert(std::constructible_from<std::ranges::wistream_view<int>, std::wist
 static_assert(!std::convertible_to<std::wistream&, std::ranges::wistream_view<int>>);
 #endif
 
+struct NoopExtraction {
+  int n_; // intentionally doesn't have default member initializer
+};
+
+template <class CharT, class Traits>
+std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, const NoopExtraction&) {
+  return is; // intentionally doesn't modify the NoopExtraction object
+}
+
 template <class CharT>
 void test() {
   // test constructor init the stream pointer to the passed one
@@ -37,12 +46,18 @@ void test() {
     assert(*it == 123);
   }
 
+  // LWG 3568. value_ must be initialized for basic_istream_view to be constexpr-constructible
+  {
+    static auto fn_local_iss            = make_string_stream<CharT>("");
+    [[maybe_unused]] constexpr auto isv = std::views::istream<int>(fn_local_iss);
+  }
+
   // LWG 3568. basic_istream_view needs to initialize value_
   {
-    auto iss = make_string_stream<CharT>("");
-    std::ranges::basic_istream_view<int, CharT> isv{iss};
-    auto iter = isv.begin();
-    assert(*iter == 0);
+    auto iss = make_string_stream<CharT>("123");
+    std::ranges::basic_istream_view<NoopExtraction, CharT> isv{iss};
+    auto it = isv.begin();
+    assert((*it).n_ == 0);
   }
 }
 


        


More information about the libcxx-commits mailing list