This patch backports the important parts of three commits from trunk to the 4.8 branch.
Tested x86_64-linux, committed to the 4.8 branch.
commit 48a2f3af4fcff86695e6f12c1490833f5679ad44 Author: Jonathan Wakely <jwak...@redhat.com> Date: Tue Mar 11 18:20:47 2014 +0000 Backport from mainline. 2014-01-09 Jonathan Wakely <jwak...@redhat.com> PR libstdc++/59738 * include/bits/stl_vector.h (vector<>::_M_move_assign): Restore support for non-Movable types. 2014-01-08 François Dumont <fdum...@gcc.gnu.org> * include/bits/stl_vector.h (std::vector<>::_M_move_assign): Pass *this allocator instance when building temporary vector instance so that *this allocator does not get moved. * testsuite/23_containers/vector/allocator/move.cc (test01): Add check on a vector iterator. * testsuite/23_containers/vector/allocator/move_assign.cc (test02): Likewise. (test03): New, test with a non-propagating allocator. 2013-11-15 Jonathan Wakely <jwakely....@gmail.com> * testsuite/23_containers/vector/allocator/move.cc: New diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 69c6e27..14de461 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1361,7 +1361,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_move_assign(vector&& __x, std::true_type) noexcept { - const vector __tmp(std::move(*this)); + vector __tmp(get_allocator()); + this->_M_impl._M_swap_data(__tmp._M_impl); 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(), diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/move.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/move.cc new file mode 100644 index 0000000..7e62f1e --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/move.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2013 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-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +struct T { int i; }; + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + auto it = v1.begin(); + test_type v2(std::move(v1)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + test_type v2(std::move(v1), alloc_type(2)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/move_assign.cc index 64795d3..42dec6d 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/allocator/move_assign.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/move_assign.cc @@ -46,16 +46,35 @@ void test02() typedef std::vector<T, alloc_type> test_type; test_type v1(alloc_type(1)); v1.push_back(T()); + auto it = v1.begin(); test_type v2(alloc_type(2)); - v2 = std::move(v1); v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); } +void test03() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + auto it = v1.begin(); + test_type v2(alloc_type(1)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + int main() { test01(); test02(); + test03(); return 0; }