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. >
