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