summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-10 22:44:07 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-10 22:44:07 +0000
commit24c4f18d7028e31f9bf1e434c59b13f389d8e7e4 (patch)
tree82b7ad8a37e5fb0f27c2cddc50136d114462233b
parent1675d1be7ee8eed319ebb548803640231c920456 (diff)
downloadgcc-24c4f18d7028e31f9bf1e434c59b13f389d8e7e4.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217322 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog14
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h50
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc2
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 <jwakely@redhat.com>
+
+ * 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 <fdumont@gcc.gnu.org>
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<typename _Tp, typename _Alloc>
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 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1859 }
+// { dg-error "no matching" "" { target *-*-* } 1881 }
#include <deque>
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 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1792 }
+// { dg-error "no matching" "" { target *-*-* } 1814 }
#include <deque>
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 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1792 }
+// { dg-error "no matching" "" { target *-*-* } 1814 }
#include <deque>
#include <utility>
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 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1943 }
+// { dg-error "no matching" "" { target *-*-* } 1965 }
#include <deque>