aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2025-02-27 13:27:17 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2025-02-28 21:35:27 +0000
commit3866ca796d5281d33f25b4165badacf8f198c6d1 (patch)
treef258fc80ee51dece3bc84c559d300d42c63ce9c8
parenta9cfcd0d9e3780c71442057f636f62a7142056cb (diff)
downloadgcc-3866ca796d5281d33f25b4165badacf8f198c6d1.zip
gcc-3866ca796d5281d33f25b4165badacf8f198c6d1.tar.gz
gcc-3866ca796d5281d33f25b4165badacf8f198c6d1.tar.bz2
libstdc++: Fix ranges::move and ranges::move_backward to use iter_move [PR105609]
The ranges::move and ranges::move_backward algorithms are supposed to use ranges::iter_move(iter) instead of std::move(*iter), which matters for an iterator type with an iter_move overload findable by ADL. Currently those algorithms use std::__assign_one which uses std::move, so define a new ranges::__detail::__assign_one helper function that uses ranges::iter_move. libstdc++-v3/ChangeLog: PR libstdc++/105609 * include/bits/ranges_algobase.h (__detail::__assign_one): New helper function. (__copy_or_move, __copy_or_move_backward): Use new function instead of std::__assign_one. * testsuite/25_algorithms/move/constrained.cc: Check that ADL iter_move is used in preference to std::move. * testsuite/25_algorithms/move_backward/constrained.cc: Likewise.
-rw-r--r--libstdc++-v3/include/bits/ranges_algobase.h26
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/move/constrained.cc29
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc29
3 files changed, 78 insertions, 6 deletions
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index eceb859..a08f659b 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -188,6 +188,20 @@ namespace ranges
inline constexpr __equal_fn equal{};
+namespace __detail
+{
+ template<bool _IsMove, typename _OutIter, typename _InIter>
+ [[__gnu__::__always_inline__]]
+ constexpr void
+ __assign_one(_OutIter& __out, _InIter& __in)
+ {
+ if constexpr (_IsMove)
+ *__out = ranges::iter_move(__in);
+ else
+ *__out = *__in;
+ }
+} // namespace __detail
+
template<typename _Iter, typename _Out>
struct in_out_result
{
@@ -291,14 +305,14 @@ namespace ranges
__builtin_memmove(__result, __first,
sizeof(_ValueTypeI) * __num);
else if (__num == 1)
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
return {__first + __num, __result + __num};
}
}
for (auto __n = __last - __first; __n > 0; --__n)
{
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
++__first;
++__result;
}
@@ -308,7 +322,7 @@ namespace ranges
{
while (__first != __last)
{
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
++__first;
++__result;
}
@@ -420,7 +434,7 @@ namespace ranges
__builtin_memmove(__result, __first,
sizeof(_ValueTypeI) * __num);
else if (__num == 1)
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
return {__first + __num, __result};
}
}
@@ -432,7 +446,7 @@ namespace ranges
{
--__tail;
--__result;
- std::__assign_one<_IsMove>(__result, __tail);
+ __detail::__assign_one<_IsMove>(__result, __tail);
}
return {std::move(__lasti), std::move(__result)};
}
@@ -445,7 +459,7 @@ namespace ranges
{
--__tail;
--__result;
- std::__assign_one<_IsMove>(__result, __tail);
+ __detail::__assign_one<_IsMove>(__result, __tail);
}
return {std::move(__lasti), std::move(__result)};
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
index 587b2f3..e2b45b0 100644
--- a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
@@ -204,6 +204,35 @@ test05()
VERIFY( ranges::equal(v, (int[]){1,2,3,0}) );
}
+namespace pr105609
+{
+ struct I {
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
+ int operator*() const;
+ I& operator++();
+ I operator++(int);
+ I& operator--();
+ I operator--(int);
+ bool operator==(I) const;
+ friend int& iter_move(const I&);
+ };
+}
+
+void
+test06(pr105609::I i)
+{
+ // PR libstdc++/105609
+ // ranges::move should use ranges::iter_move instead of std::move
+ struct O {
+ O(int&) { }
+ O(int&&) = delete;
+ };
+
+ O* o = nullptr;
+ std::ranges::move(i, i, o);
+}
+
int
main()
{
diff --git a/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc
index 8f6fd45..4d94d38 100644
--- a/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc
@@ -160,6 +160,35 @@ test03()
return ok;
}
+namespace pr105609
+{
+ struct I {
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
+ int operator*() const;
+ I& operator++();
+ I operator++(int);
+ I& operator--();
+ I operator--(int);
+ bool operator==(I) const;
+ friend int& iter_move(const I&);
+ };
+}
+
+void
+test04(pr105609::I i)
+{
+ // PR libstdc++/105609
+ // ranges::move should use ranges::iter_move instead of std::move
+ struct O {
+ O(int&) { }
+ O(int&&) = delete;
+ };
+
+ O* o = nullptr;
+ std::ranges::move_backward(i, i, o);
+}
+
int
main()
{