aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely.gcc@gmail.com>2012-04-01 22:04:54 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2012-04-01 23:04:54 +0100
commitea2c1a6d673c443effb1adbc652143c2b3934a5d (patch)
tree9c3ee73c94a8d2af8568e44388d7d72df4b572dd
parent181c9de2a6d42430f66fe1374d84208703bd0ac3 (diff)
downloadgcc-ea2c1a6d673c443effb1adbc652143c2b3934a5d.zip
gcc-ea2c1a6d673c443effb1adbc652143c2b3934a5d.tar.gz
gcc-ea2c1a6d673c443effb1adbc652143c2b3934a5d.tar.bz2
re PR libstdc++/52591 ([C++0x] [4.7 Regression] moving std::vector relies on movable elements)
PR libstdc++/52591 * include/bits/stl_vector.h (vector::operator=(vector&&)): Dispatch to _M_move_assign depending on whether allocator is moved. (vector::_M_move_assign): Add overloaded functions. * testsuite/23_containers/vector/52591.cc: New. * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: Adjust dg-error line number. * testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: Likewise. From-SVN: r186057
-rw-r--r--libstdc++-v3/ChangeLog16
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h65
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/52591.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc2
7 files changed, 98 insertions, 29 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6f4e7bf..66bf6de 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,21 @@
2012-04-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+ PR libstdc++/52591
+ * include/bits/stl_vector.h (vector::operator=(vector&&)): Dispatch
+ to _M_move_assign depending on whether allocator is moved.
+ (vector::_M_move_assign): Add overloaded functions.
+ * testsuite/23_containers/vector/52591.cc: New.
+ * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
+ Adjust dg-error line number.
+ * testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc:
+ Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc:
+ Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
+ Likewise.
+
+2012-04-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+
* include/std/functional (__callable_functor): Overload for
volatile-qualified pointers.
* testsuite/20_util/function/10.cc: New.
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 239f8b9..31660d3 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -428,36 +428,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @brief %Vector move assignment operator.
* @param __x A %vector of identical element and allocator types.
*
- * The contents of @a __x are moved into this %vector (without copying).
+ * The contents of @a __x are moved into this %vector (without copying,
+ * if the allocators permit it).
* @a __x is a valid, but unspecified %vector.
*/
vector&
operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
{
- if (_Alloc_traits::_S_propagate_on_move_assign())
- {
- // We're moving the rvalue's allocator so can move the data too.
- const vector __tmp(std::move(*this)); // discard existing data
- this->_M_impl._M_swap_data(__x._M_impl);
- std::__alloc_on_move(_M_get_Tp_allocator(),
- __x._M_get_Tp_allocator());
- }
- else if (_Alloc_traits::_S_always_equal()
- || __x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
- {
- // The rvalue's allocator can free our storage and vice versa,
- // so can swap the data storage after destroying our contents.
- this->clear();
- this->_M_impl._M_swap_data(__x._M_impl);
- }
- else
- {
- // The rvalue's allocator cannot be moved, or is not equal,
- // so we need to individually move each element.
- this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
- std::__make_move_if_noexcept_iterator(__x.end()));
- __x.clear();
- }
+ constexpr bool __move_storage =
+ _Alloc_traits::_S_propagate_on_move_assign()
+ || _Alloc_traits::_S_always_equal();
+ _M_move_assign(std::move(__x),
+ integral_constant<bool, __move_storage>());
return *this;
}
@@ -1363,6 +1345,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
this->_M_impl._M_finish = __pos;
}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ private:
+ // Constant-time move assignment when source object's memory can be
+ // moved, either because the source's allocator will move too
+ // or because the allocators are equal.
+ void
+ _M_move_assign(vector&& __x, std::true_type) noexcept
+ {
+ const vector __tmp(std::move(*this));
+ this->_M_impl._M_swap_data(__x._M_impl);
+ if (_Alloc_traits::_S_propagate_on_move_assign())
+ std::__alloc_on_move(_M_get_Tp_allocator(),
+ __x._M_get_Tp_allocator());
+ }
+
+ // Do move assignment when it might not be possible to move source
+ // object's memory, resulting in a linear-time operation.
+ void
+ _M_move_assign(vector&& __x, std::false_type)
+ {
+ if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
+ _M_move_assign(std::move(__x), std::true_type());
+ else
+ {
+ // The rvalue's allocator cannot be moved and is not equal,
+ // so we need to individually move each element.
+ this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
+ std::__make_move_if_noexcept_iterator(__x.end()));
+ __x.clear();
+ }
+ }
+#endif
};
diff --git a/libstdc++-v3/testsuite/23_containers/vector/52591.cc b/libstdc++-v3/testsuite/23_containers/vector/52591.cc
new file mode 100644
index 0000000..c018c72
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/52591.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2012 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// libstdc++/52591
+
+#include <vector>
+
+// As an extension we allow move-assignment of std::vector when the element
+// type is not MoveAssignable, as long as the allocator type propagates or
+// is known to always compare equal.
+
+struct C
+{
+ C& operator=(C&&) = delete;
+};
+
+void test01()
+{
+ std::vector<C> a;
+ a = std::vector<C>();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
index 73de8ae..644750c 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1251 }
+// { dg-error "no matching" "" { target *-*-* } 1233 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
index fa479c7..bbd4cfe 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1181 }
+// { dg-error "no matching" "" { target *-*-* } 1163 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
index 231cace..d2282cc 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1181 }
+// { dg-error "no matching" "" { target *-*-* } 1163 }
#include <vector>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
index b8e18bb..d2cde66 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1292 }
+// { dg-error "no matching" "" { target *-*-* } 1274 }
#include <vector>