mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-29 05:55:44 +08:00
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
This commit is contained in:
parent
181c9de2a6
commit
ea2c1a6d67
@ -1,3 +1,19 @@
|
||||
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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
38
libstdc++-v3/testsuite/23_containers/vector/52591.cc
Normal file
38
libstdc++-v3/testsuite/23_containers/vector/52591.cc
Normal file
@ -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>();
|
||||
}
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user