From 2abd4ee6b507ce4ed4cc1591e616e0abb0740cfb Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 10 Nov 2014 22:44:07 +0000 Subject: [PATCH] Fix std::deque move construction with non-equal allocators. * include/bits/stl_deque.h (_Deque_base::_Deque_base(_Deque_base&&)): Dispatch according to whether allocators are always equal. (_Deque_base::_M_move_impl()): Implement move-from state. * testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Fix dg-error line number. * testsuite/23_containers/deque/requirements/dr438/ constructor_1_neg.cc: Likewise. * testsuite/23_containers/deque/requirements/dr438/ constructor_2_neg.cc: Likewise. * testsuite/23_containers/deque/requirements/dr438/insert_neg.cc: Likewise. From-SVN: r217322 --- libstdc++-v3/ChangeLog | 14 ++++++ libstdc++-v3/include/bits/stl_deque.h | 50 ++++++++++++++++--- .../deque/requirements/dr438/assign_neg.cc | 2 +- .../requirements/dr438/constructor_1_neg.cc | 2 +- .../requirements/dr438/constructor_2_neg.cc | 2 +- .../deque/requirements/dr438/insert_neg.cc | 2 +- 6 files changed, 60 insertions(+), 12 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 33aa6f03041..0f33b7aa5ad 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,17 @@ +2014-11-10 Jonathan Wakely + + * include/bits/stl_deque.h (_Deque_base::_Deque_base(_Deque_base&&)): + Dispatch according to whether allocators are always equal. + (_Deque_base::_M_move_impl()): Implement move-from state. + * testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Fix + dg-error line number. + * testsuite/23_containers/deque/requirements/dr438/ + constructor_1_neg.cc: Likewise. + * testsuite/23_containers/deque/requirements/dr438/ + constructor_2_neg.cc: Likewise. + * testsuite/23_containers/deque/requirements/dr438/insert_neg.cc: + Likewise. + 2014-11-10 François Dumont Major maintenance patch of the profile mode. diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index d50d3c90991..c0052b39b04 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -502,14 +502,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { /* Caller must initialize map. */ } #if __cplusplus >= 201103L - _Deque_base(_Deque_base&& __x) - : _M_impl(__x._M_get_Tp_allocator()) + _Deque_base(_Deque_base&& __x, false_type) + : _M_impl(__x._M_move_impl()) + { } + + _Deque_base(_Deque_base&& __x, true_type) + : _M_impl(std::move(__x._M_get_Tp_allocator())) { _M_initialize_map(0); if (__x._M_impl._M_map) this->_M_impl._M_swap_data(__x._M_impl); } + _Deque_base(_Deque_base&& __x) + : _Deque_base(std::move(__x), + __gnu_cxx::__allocator_always_compares_equal<_Alloc>{}) + { } + _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n) : _M_impl(__a) { @@ -555,18 +564,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { } #if __cplusplus >= 201103L - _Deque_impl(_Tp_alloc_type&& __a) _GLIBCXX_NOEXCEPT + _Deque_impl(_Deque_impl&&) = default; + + _Deque_impl(_Tp_alloc_type&& __a) noexcept : _Tp_alloc_type(std::move(__a)), _M_map(), _M_map_size(0), _M_start(), _M_finish() { } #endif - void _M_swap_data(_Deque_impl& __x) + void _M_swap_data(_Deque_impl& __x) _GLIBCXX_NOEXCEPT { - std::swap(this->_M_start, __x._M_start); - std::swap(this->_M_finish, __x._M_finish); - std::swap(this->_M_map, __x._M_map); - std::swap(this->_M_map_size, __x._M_map_size); + using std::swap; + swap(this->_M_start, __x._M_start); + swap(this->_M_finish, __x._M_finish); + swap(this->_M_map, __x._M_map); + swap(this->_M_map_size, __x._M_map_size); } }; @@ -618,6 +630,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER enum { _S_initial_map_size = 8 }; _Deque_impl _M_impl; + +#if __cplusplus >= 201103L + private: + _Deque_impl + _M_move_impl() + { + if (!_M_impl._M_map) + return std::move(_M_impl); + + // Create a copy of the current allocator. + _Tp_alloc_type __alloc{_M_get_Tp_allocator()}; + // Put that copy in a moved-from state. + _Tp_alloc_type __unused __attribute((__unused__)) {std::move(__alloc)}; + // Create an empty map that allocates using the moved-from allocator. + _Deque_base __empty{__alloc}; + // Now safe to modify current allocator and perform non-throwing swaps. + _Deque_impl __ret{std::move(_M_get_Tp_allocator())}; + _M_impl._M_swap_data(__ret); + _M_impl._M_swap_data(__empty._M_impl); + return __ret; + } +#endif }; template diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc index 8092ead6d41..b38f3ae45c3 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1859 } +// { dg-error "no matching" "" { target *-*-* } 1881 } #include diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc index 4abdf4682be..a30029a0395 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1792 } +// { dg-error "no matching" "" { target *-*-* } 1814 } #include diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc index 61bce4eb049..02eba79b9cf 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1792 } +// { dg-error "no matching" "" { target *-*-* } 1814 } #include #include diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc index a0ca00caf8a..8c1dd2e949f 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1943 } +// { dg-error "no matching" "" { target *-*-* } 1965 } #include -- 2.30.2