From: Jonathan Wakely Date: Thu, 27 Feb 2025 13:27:17 +0000 (+0000) Subject: libstdc++: Fix ranges::move and ranges::move_backward to use iter_move [PR105609] X-Git-Tag: basepoints/gcc-16~1788 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3866ca796d5281d33f25b4165badacf8f198c6d1;p=thirdparty%2Fgcc.git 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. --- diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index eceb859e88ba..a08f659b3aef 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 + [[__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 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 587b2f3728b1..e2b45b070ef2 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 8f6fd455b4b6..4d94d386dd0b 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() {