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.

Reply via email to