On Tue, 24 Feb 2026 at 10:15, Avi Kivity <[email protected]> wrote: > > > > On Thu, Feb 19, 2026 at 7:48 PM Avi Kivity <[email protected]> wrote: >> >> >> >> On Tue, Feb 17, 2026 at 12:31 PM Avi Kivity <[email protected]> wrote: >>> >>> >>> >>> On Tue, Feb 17, 2026 at 11:44 AM Jonathan Wakely <[email protected]> >>> wrote: >>>> >>>> >>>> >>>> On Mon, 16 Feb 2026, 19:48 Avi Kivity, <[email protected]> wrote: >>>>> >>>>> >>>>> >>>>> On Mon, Feb 16, 2026 at 8:29 PM Jonathan Wakely <[email protected]> >>>>> wrote: >>>>>> >>>>>> On Mon, 16 Feb 2026 at 17:59, Avi Kivity <[email protected]> wrote: >>>>>> > >>>>>> > std::uninitialized_move{,_n} delegates to the corresponding >>>>>> > std::uninitialized_copy() variant after wrapping with a move >>>>>> > iterator, but the std::uninitialized_copy() doesn't unwrap the >>>>>> > move iterator, therefore losing the memcpy optimization if the >>>>>> > iterators were just pointers. >>>>>> > >>>>>> > Fix this by unwrapping the move iterator using __miter_base(). To >>>>>> > prevent some greedy_ops tests starting to fail by consuming the >>>>>> > pointer difference, we have to unwrap the move iterator before >>>>>> > computing >>>>>> > the iterator difference as well. >>>>>> > >>>>>> > libstdc++v3/Changelog: >>>>>> > >>>>>> > PR libstdc++/121789 >>>>>> > * include/bits/stl_uninitialized.h (uninitialized_copy): >>>>>> > Unwrap move iterators >>>>>> > * >>>>>> > testsuite/20_util/specialized_algorithms/uninitialized_move/121789.cc: >>>>>> > New test. >>>>>> > --- >>>>>> > >>>>>> > Disclosure: I was assisted by AI. >>>>>> > >>>>>> > libstdc++-v3/include/bits/stl_uninitialized.h | 8 ++-- >>>>>> > .../uninitialized_move/121789.cc | 37 +++++++++++++++++++ >>>>>> > 2 files changed, 42 insertions(+), 3 deletions(-) >>>>>> > create mode 100644 >>>>>> > libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/121789.cc >>>>>> > >>>>>> > diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h >>>>>> > b/libstdc++-v3/include/bits/stl_uninitialized.h >>>>>> > index 82e4ba2ff7b..fa9d896fefc 100644 >>>>>> > --- a/libstdc++-v3/include/bits/stl_uninitialized.h >>>>>> > +++ b/libstdc++-v3/include/bits/stl_uninitialized.h >>>>>> > @@ -273,11 +273,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>>>>> > // We cannot tell when this condition is true in general, >>>>>> > // so we rely on the __memcpyable trait. >>>>>> > >>>>>> > #if __cplusplus >= 201103L >>>>>> > using _Dest = decltype(std::__niter_base(__result)); >>>>>> > - using _Src = decltype(std::__niter_base(__first)); >>>>>> > + using _Src = >>>>>> > decltype(std::__miter_base(std::__niter_base(__first))); >>>>>> > using _ValT = typename >>>>>> > iterator_traits<_ForwardIterator>::value_type; >>>>>> > >>>>>> > #if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 >>>>>> > if consteval { >>>>>> > return std::__do_uninit_copy(__first, __last, __result); >>>>>> > @@ -285,16 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>>>>> > #endif >>>>>> > if constexpr (!__is_trivially_constructible(_ValT, >>>>>> > decltype(*__first))) >>>>>> > return std::__do_uninit_copy(__first, __last, __result); >>>>>> > else if constexpr (__memcpyable<_Dest, _Src>::__value) >>>>>> > { >>>>>> > - ptrdiff_t __n = __last - __first; >>>>>> > + ptrdiff_t __n >>>>>> > + = std::__miter_base(std::__niter_base(__last)) >>>>>> > + - std::__miter_base(std::__niter_base(__first)); >>>>>> >>>>>> This change seems completely unnecessary (I blame the AI assistance). >>>>>> >>>>> >>>>> It is necessary. Without it, 23_containers/vector/types/1.cc will not >>>>> compile since greedy_ops' >>>>> operator- will fight with the move iterator's operator-. I mentioned it >>>>> in the commit changelog. >>>> >>>> >>>> But that's more evidence that the greedy_ops tests are invalid C++. >>> >>> >>> Shall I send a patch to remove them? >>> >>>> >>>> Or if we still care about them, we should fix move_iterator. >>>> >>> >>> I can't make that call. >>> >> >> How should I proceed? Patch greedy_ops out of existence, or keep this line? >> >> Personally I think this line is fine (if we're happy to unwrap to get the >> pointer, we should be happy to unwrap to get the range size), AND that >> attempting to harden against something like greedy_ops is futile. >> >> > > > Pinging for direction.
I need to page back in various bits of ancient history like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71771 The 24_iterators/move_iterator/greedy_ops.cc test explicitly comments out the subtraction, because it's known to not work (and refers to the above bug). Maybe we should just do this: --- a/libstdc++-v3/testsuite/util/testsuite_greedy_ops.h +++ b/libstdc++-v3/testsuite/util/testsuite_greedy_ops.h @@ -46,10 +46,10 @@ namespace greedy_ops X operator>=(T, T) { return X(); } + /* template<typename T> X operator-(T, T) { return X(); } - /* template<typename T> T operator+(std::size_t, T) { return T(); } Could you add that to your patch? That should allow you to drop the change to the __last - __first expression.
