]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Some concat_view bugfixes [PR115215, PR115218, LWG 4082]
authorPatrick Palka <ppalka@redhat.com>
Wed, 5 Mar 2025 16:11:35 +0000 (11:11 -0500)
committerPatrick Palka <ppalka@redhat.com>
Wed, 5 Mar 2025 16:11:35 +0000 (11:11 -0500)
- Use __builtin_unreachable to suppress a false-positive "control
  reaches end of non-void function" warning in the recursive lambda
  (which the existing tests failed to notice since test01 wasn't
  being called at runtime)
- Relax the constraints on views::concat in the single-argument case
  as per PR115215
- Add an input_range requirement to that same case as per LWG 4082
- In the const-converting constructor of concat_view's iterator,
  don't require the first iterator to be default constructible

PR libstdc++/115215
PR libstdc++/115218

libstdc++-v3/ChangeLog:

* include/std/ranges
(concat_view::iterator::_S_invoke_with_runtime_index): Use
__builtin_unreachable in recursive lambda to certify it always
exits via 'return'.
(concat_view::iterator::iterator): In the const-converting
constructor, direct initialize _M_it.
(views::_Concat::operator()): Adjust constraints in the
single-argument case as per LWG 4082.
* testsuite/std/ranges/concat/1.cc (test01): Call it at runtime
too.
(test04): New test.

Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/concat/1.cc

index c0b1134ab328aff1625fa48c9af1ed86d6edfc1e..def7527431cdc0dbe77a2c34bdf5a89dba746e73 100644 (file)
@@ -9922,6 +9922,7 @@ namespace ranges
            return __f.template operator()<_Idx>();
          if constexpr (_Idx + 1 < sizeof...(_Vs))
            return __self.template operator()<_Idx + 1>();
+         __builtin_unreachable();
        }.template operator()<0>();
       }
 
@@ -9943,12 +9944,12 @@ namespace ranges
     constexpr
     _Iterator(_Iterator<!_Const> __it)
       requires _Const && (convertible_to<iterator_t<_Vs>, iterator_t<const _Vs>> && ...)
-    : _M_parent(__it._M_parent)
-    {
-      _M_invoke_with_runtime_index([this, &__it]<size_t _Idx>() {
-       _M_it.template emplace<_Idx>(std::get<_Idx>(std::move(__it._M_it)));
-      });
-    }
+    : _M_parent(__it._M_parent),
+      _M_it(_S_invoke_with_runtime_index([this, &__it]<size_t _Idx>() {
+             return __base_iter(in_place_index<_Idx>,
+                                std::get<_Idx>(std::move(__it._M_it)));
+           }, __it._M_it.index()))
+    }
 
     constexpr decltype(auto)
     operator*() const
@@ -10186,12 +10187,12 @@ namespace ranges
        requires __detail::__can_concat_view<_Ts...>
       constexpr auto
       operator() [[nodiscard]] (_Ts&&... __ts) const
-      {
-       if constexpr (sizeof...(_Ts) == 1)
-         return views::all(std::forward<_Ts>(__ts)...);
-       else
-         return concat_view(std::forward<_Ts>(__ts)...);
-      }
+      { return concat_view(std::forward<_Ts>(__ts)...); }
+
+      template<input_range _Range>
+      constexpr auto
+      operator() [[nodiscard]] (_Range&& __t) const
+      { return views::all(std::forward<_Range>(__t)); }
     };
 
     inline constexpr _Concat concat;
index e5d10f476e93f9f16f8eb0998fadcfc706c6c4a7..16721912a37d143a26f8a1663749116899550f13 100644 (file)
@@ -85,10 +85,26 @@ test03()
   VERIFY( ranges::equal(view2, std::vector{4, 5, 6, 1, 2, 3}) );
 }
 
+void
+test04()
+{
+  // PR libstdc++/115215 - views::concat rejects non-movable reference
+  int x[] = {1,2,3};
+  struct nomove {
+    nomove() = default;
+    nomove(const nomove&) = delete;
+  };
+  auto v = x | views::transform([](int) { return nomove{}; });
+  using type = decltype(views::concat(v));
+  using type = decltype(v);
+}
+
 int
 main()
 {
   static_assert(test01());
+  test01();
   test02();
   test03();
+  test04();
 }