From: Jonathan Wakely Date: Tue, 23 Aug 2016 13:15:12 +0000 (+0100) Subject: libstdc++/77334 move assign RB trees of non-copyable types X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5ea387db6c1eddc8a242d261ed2df1552222663c;p=gcc.git libstdc++/77334 move assign RB trees of non-copyable types PR libstdc++/77334 * include/bits/stl_tree.h (_Rb_tree::_M_move_assign): New functions. (_Rb_tree::operator=(_Rb_tree&&)): Dispatch to _M_move_assign. * testsuite/23_containers/map/77334.cc: New test. From-SVN: r239698 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ddbbb73d3cc..5e943b130d8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,10 @@ 2016-08-23 Jonathan Wakely + PR libstdc++/77334 + * include/bits/stl_tree.h (_Rb_tree::_M_move_assign): New functions. + (_Rb_tree::operator=(_Rb_tree&&)): Dispatch to _M_move_assign. + * testsuite/23_containers/map/77334.cc: New test. + * doc/xml/manual/using.xml: Remove reference to -pthreads option. * doc/html/*: Regenerate. diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 8697a711a5f..25580e4cc5c 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1264,6 +1264,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // which might result in a copy not a move. void _M_move_data(_Rb_tree&, std::false_type); + + // Move assignment from container with equal allocator. + void + _M_move_assign(_Rb_tree&, std::true_type); + + // Move assignment from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_assign(_Rb_tree&, std::false_type); #endif }; @@ -1379,24 +1388,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + inline void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - operator=(_Rb_tree&& __x) - noexcept(_Alloc_traits::_S_nothrow_move() - && is_nothrow_move_assignable<_Compare>::value) + _M_move_assign(_Rb_tree& __x, true_type) { - _M_impl._M_key_compare = __x._M_impl._M_key_compare; - if (_Alloc_traits::_S_propagate_on_move_assign() - || _Alloc_traits::_S_always_equal() - || _M_get_Node_allocator() == __x._M_get_Node_allocator()) - { - clear(); - if (__x._M_root() != nullptr) - _M_move_data(__x, std::true_type()); - std::__alloc_on_move(_M_get_Node_allocator(), - __x._M_get_Node_allocator()); - return *this; - } + clear(); + if (__x._M_root() != nullptr) + _M_move_data(__x, std::true_type()); + std::__alloc_on_move(_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + return _M_move_assign(__x, true_type{}); // Try to move each node reusing existing nodes and copying __x nodes // structure. @@ -1416,6 +1426,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_impl._M_node_count = __x._M_impl._M_node_count; __x.clear(); } + } + + template + inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(_Rb_tree&& __x) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value) + { + _M_impl._M_key_compare = __x._M_impl._M_key_compare; + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign() + || _Alloc_traits::_S_always_equal(); + _M_move_assign(__x, __bool_constant<__move_storage>()); return *this; } diff --git a/libstdc++-v3/testsuite/23_containers/map/77334.cc b/libstdc++-v3/testsuite/23_containers/map/77334.cc new file mode 100644 index 00000000000..917896bed2b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/map/77334.cc @@ -0,0 +1,28 @@ +// Copyright (C) 2016 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 +// . + +// { dg-do compile { target c++11 } } + +#include + +struct A { A(A&&) = delete; }; + +void test01() +{ + std::map m1, m2; + m2 = std::move(m1); +}