[libcxx-commits] [libcxx] e74be35 - [libc++][ranges] LWG3984: ranges::to's recursion branch may be ill-formed (#87964)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Apr 26 08:00:51 PDT 2024


Author: Xiaoyang Liu
Date: 2024-04-26T11:00:47-04:00
New Revision: e74be35c1abedf87cfaa141284cb730911211ee1

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

LOG: [libc++][ranges] LWG3984: ranges::to's recursion branch may be ill-formed (#87964)

This pull request implements LWG3984: ranges::to's recursion branch
may be ill-formed.

In the current implementation, ranges::to's recursion branch pipes the
range into a `views::transform(/* lambda */)`, which is a __range_adaptor_closure
object. In libc++, the pipe operator of __range_adaptor_closure requires a
viewable_range, so the following code won't compile, as the type of lvalue
`r` doesn't model viewable_range:

  #include <ranges>
  #include <vector>
  #include <list>

  int main() {
    std::vector<std::vector<int>> v;
    auto r = std::views::all(std::move(v));
    auto l = std::ranges::to<std::list<std::list<int>>>(r);
  }

Co-authored-by: A. Jiang <de34 at live.cn>

Added: 
    

Modified: 
    libcxx/docs/Status/Cxx2cIssues.csv
    libcxx/include/__ranges/to.h
    libcxx/test/std/ranges/range.utility/range.utility.conv/to.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 666be319757c17..eb99414c48be12 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -44,7 +44,7 @@
 "`3919 <https://wg21.link/LWG3919>`__","``enumerate_view`` may invoke UB for sized common non-forward underlying ranges","Tokyo March 2024","","","|ranges|"
 "`3950 <https://wg21.link/LWG3950>`__","``std::basic_string_view`` comparison operators are overspecified","Tokyo March 2024","|Complete|","18.0",""
 "`3975 <https://wg21.link/LWG3975>`__","Specializations of ``basic_format_context`` should not be permitted","Tokyo March 2024","|Nothing To Do|","","|format|"
-"`3984 <https://wg21.link/LWG3984>`__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","","","|ranges|"
+"`3984 <https://wg21.link/LWG3984>`__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","|Complete|","19.0","|ranges|"
 "`4011 <https://wg21.link/LWG4011>`__","``""Effects: Equivalent to return""`` in ``[span.elem]``","Tokyo March 2024","|Nothing To Do|","",""
 "`4012 <https://wg21.link/LWG4012>`__","``common_view::begin/end`` are missing the ``simple-view`` check","Tokyo March 2024","","","|ranges|"
 "`4013 <https://wg21.link/LWG4013>`__","``lazy_split_view::outer-iterator::value_type`` should not provide default constructor","Tokyo March 2024","","","|ranges|"

diff  --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h
index 8a815bce58111e..e0abe6290b8f7d 100644
--- a/libcxx/include/__ranges/to.h
+++ b/libcxx/include/__ranges/to.h
@@ -24,6 +24,7 @@
 #include <__ranges/concepts.h>
 #include <__ranges/from_range.h>
 #include <__ranges/range_adaptor.h>
+#include <__ranges/ref_view.h>
 #include <__ranges/size.h>
 #include <__ranges/transform_view.h>
 #include <__type_traits/add_pointer.h>
@@ -129,7 +130,7 @@ template <class _Container, input_range _Range, class... _Args>
     // Try the recursive case.
   } else if constexpr (input_range<range_reference_t<_Range>>) {
     return ranges::to<_Container>(
-        __range | views::transform([](auto&& __elem) {
+        ref_view(__range) | views::transform([](auto&& __elem) {
           return ranges::to<range_value_t<_Container>>(std::forward<decltype(__elem)>(__elem));
         }),
         std::forward<_Args>(__args)...);

diff  --git a/libcxx/test/std/ranges/range.utility/range.utility.conv/to.pass.cpp b/libcxx/test/std/ranges/range.utility/range.utility.conv/to.pass.cpp
index 3df88d6a2dcc38..7f816bb21a1978 100644
--- a/libcxx/test/std/ranges/range.utility/range.utility.conv/to.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/range.utility.conv/to.pass.cpp
@@ -560,6 +560,11 @@ constexpr void test_recursive() {
   }
 
   assert((in | std::ranges::to<C4>()) == result);
+
+  // LWG3984: ranges::to's recursion branch may be ill-formed
+  auto in_owning_view = std::views::all(std::move(in));
+  static_assert(!std::ranges::viewable_range<decltype((in_owning_view))>);
+  assert(std::ranges::to<C4>(in_owning_view) == result);
 }
 
 constexpr bool test() {


        


More information about the libcxx-commits mailing list