On Fri, 19 Sept 2025, 19:19 Ben Wu, <soggysocks...@gmail.com> wrote:

> Ok, I've added those changes to the attached patch. Testing in progress.
>

I've pushed this to trunk now, thanks for fixing it!



> Thanks,
> -Ben
>
> -- 8< --
>
> In order to emplace a value in the middle of a deque, a temporary was
> previously constructed directly with __args... in _M_emplace_aux.
> This would not work since std::deque is allocator-aware and should
> construct elements with _Alloc_traits::construct instead before the
> element is moved.
>
> Using the suggestion in PR118087, we can define _Temporary_value
> similar to the one used in std::vector, so the temporary can be
> constructed with uses-allocator construction.
>
> PR libstdc++/118087
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/deque.tcc: Use _Temporary_value in
> _M_emplace_aux.
> * include/bits/stl_deque.h: Introduce _Temporary_value.
> * testsuite/23_containers/deque/modifiers/emplace/118087.cc:
> New test.
>
> Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
> Signed-off-by: Ben Wu <soggysocks...@gmail.com>
> ---
>  libstdc++-v3/include/bits/deque.tcc           | 11 ++++-
>  libstdc++-v3/include/bits/stl_deque.h         | 29 +++++++++++++
>  .../deque/modifiers/emplace/118087.cc         | 43 +++++++++++++++++++
>  3 files changed, 81 insertions(+), 2 deletions(-)
>  create mode 100644
> libstdc++-v3/testsuite/23_containers/deque/modifiers/emplace/118087.cc
>
> diff --git a/libstdc++-v3/include/bits/deque.tcc
> b/libstdc++-v3/include/bits/deque.tcc
> index dabb6ec5365..c15b046691e 100644
> --- a/libstdc++-v3/include/bits/deque.tcc
> +++ b/libstdc++-v3/include/bits/deque.tcc
> @@ -664,7 +664,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>        deque<_Tp, _Alloc>::
>        _M_emplace_aux(iterator __pos, _Args&&... __args)
>        {
> - value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy
> + // We should construct this temporary while the deque is
> + // in its current state in case something in __args...
> + // depends on that state before shuffling elements around.
> + _Temporary_value __tmp(this, std::forward<_Args>(__args)...);
>  #else
>      typename deque<_Tp, _Alloc>::iterator
>        deque<_Tp, _Alloc>::
> @@ -695,7 +698,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>      __pos = this->_M_impl._M_start + __index;
>      _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1);
>    }
> - *__pos = _GLIBCXX_MOVE(__x_copy);
> +#if __cplusplus >= 201103L
> + *__pos = std::move(__tmp._M_val());
> +#else
> + *__pos = __x_copy;
> +#endif
>   return __pos;
>        }
>
> diff --git a/libstdc++-v3/include/bits/stl_deque.h
> b/libstdc++-v3/include/bits/stl_deque.h
> index 7055641ad4e..7cc711efca8 100644
> --- a/libstdc++-v3/include/bits/stl_deque.h
> +++ b/libstdc++-v3/include/bits/stl_deque.h
> @@ -2163,6 +2163,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>        iterator
>        _M_insert_aux(iterator __pos, const value_type& __x);
>  #else
> +      struct _Temporary_value
> +      {
> + template<typename... _Args>
> +  _GLIBCXX20_CONSTEXPR explicit
> +  _Temporary_value(deque* __deque, _Args&&... __args) : _M_this(__deque)
> +  {
> +    _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
> +     std::forward<_Args>(__args)...);
> +  }
> +
> + _GLIBCXX20_CONSTEXPR
> + ~_Temporary_value()
> + { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
> +
> + _GLIBCXX20_CONSTEXPR value_type&
> + _M_val() noexcept { return __tmp_val; }
> +
> +      private:
> + _GLIBCXX20_CONSTEXPR _Tp*
> + _M_ptr() noexcept { return std::__addressof(__tmp_val); }
> +
> + union
> + {
> +  _Tp __tmp_val;
> + };
> +
> + deque* _M_this;
> +      };
> +
>        iterator
>        _M_insert_aux(iterator __pos, const value_type& __x)
>        { return _M_emplace_aux(__pos, __x); }
> diff --git
> a/libstdc++-v3/testsuite/23_containers/deque/modifiers/emplace/118087.cc
> b/libstdc++-v3/testsuite/23_containers/deque/modifiers/emplace/118087.cc
> new file mode 100644
> index 00000000000..33b7c4cee0b
> --- /dev/null
> +++
> b/libstdc++-v3/testsuite/23_containers/deque/modifiers/emplace/118087.cc
> @@ -0,0 +1,43 @@
> +// { dg-do run { target c++11 } }
> +
> +#include <testsuite_allocator.h>
> +#include <testsuite_hooks.h>
> +#include <deque>
> +#include <scoped_allocator>
> +
> +template <typename T>
> +using Alloc = __gnu_test::propagating_allocator<T, true>;
> +
> +struct X
> +{
> +  using allocator_type = Alloc<int>;
> +  X() { }
> +  X(const X&) { }
> +  X(X&&) { }
> +  X(const allocator_type& a) : alloc(a) { }
> +  X(const X&, const allocator_type& a) : alloc(a) { }
> +  X(X&&, const allocator_type& a) : alloc(a) { }
> +
> +  X& operator=(const X&) = default;
> +
> +  allocator_type alloc{-1};
> +};
> +
> +int main()
> +{
> +
> +  std::deque<X, std::scoped_allocator_adaptor<Alloc<X>>> d(2,
> Alloc<X>(50));
> +  VERIFY(d[0].alloc.get_personality() == 50);
> +  VERIFY(d[1].alloc.get_personality() == 50);
> +
> +  d.emplace(d.begin() + 1);
> +  VERIFY(d[1].alloc.get_personality() == 50);
> +
> +  d.emplace_front();
> +  VERIFY(d[0].alloc.get_personality() == 50);
> +
> +  d.emplace_back();
> +  VERIFY(d[d.size() - 1].alloc.get_personality() == 50);
> +
> +  return 0;
> +}
> --
> 2.43.0
>
> On Fri, Sep 19, 2025 at 4:26 AM Jonathan Wakely <jwak...@redhat.com>
> wrote:
>
>> On Fri, 19 Sept 2025 at 11:56, Jonathan Wakely <jwak...@redhat.com>
>> wrote:
>> >
>> > On Thu, 18 Sep 2025 at 18:52 -0700, Ben Wu wrote:
>> > >Bootstrapped and tested with check-target-libstdc++-v3 on
>> > >x86_64-pc-linux-gnu.
>> > >
>> > >Could someone help review and commit?
>> > >
>> > >For applying, please use the attached patch file since my email client
>> has
>> > >not preserved
>> > >the tabs.
>> > >
>> > >Thanks,
>> > >-Ben
>> > >
>> > >-- 8< --
>> > >
>> > >In order to emplace a value in the middle of a deque, a temporary was
>> > >previously constructed directly with __args... in _M_emplace_aux.
>> > >This would not work since std::deque is allocator-aware and should
>> > >construct elements with _Alloc_traits::construct instead before the
>> > >element is moved.
>> > >
>> > >Using the suggestion in PR118087, we can define _Temporary_value
>> > >similar to the one used in std::vector, so the temporary can be
>> > >constructed with uses-allocator construction.
>> > >
>> > >PR libstdc++/118087
>> > >
>> > >libstdc++-v3/ChangeLog:
>> > >
>> > >* include/bits/deque.tcc: Use _Temporary_value in
>> > >_M_emplace_aux.
>> > >* include/bits/stl_deque.h: Introduce _Temporary_value.
>> > >* testsuite/23_containers/deque/modifiers/emplace/118087.cc:
>> > >New test.
>> > >
>>
>>
>> In order to apply the patch we need to satisfy a legal prerequisite:
>> https://gcc.gnu.org/contribute.html#legal
>> If you don't have a copyright assignment for GCC on file with the FSF,
>> you can contribute the patch under the DCO terms:
>> https://gcc.gnu.org/dco.html
>> If you want to use the DCO could you please read the link above
>> carefully and if it applies to your contribution then amend the patch
>> or just reply to this email with the sign-off line.
>>
>>

Reply via email to