summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-23 13:15:12 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-23 13:15:12 +0000
commit2d2985b1685104778a404192dca50d35172b60e7 (patch)
tree7fb0c286c829219a9df5322e0b6d9dff281bfe28 /libstdc++-v3
parent4c11ef7ef005bdf0d05e1336c72f2a03fdf63ef4 (diff)
downloadgcc-2d2985b1685104778a404192dca50d35172b60e7.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239698 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog5
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h57
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/77334.cc28
3 files changed, 74 insertions, 16 deletions
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 <jwakely@redhat.com>
+ 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<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
- _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<typename _Key, typename _Val, typename _KeyOfValue,
+ typename _Compare, typename _Alloc>
+ 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<typename _Key, typename _Val, typename _KeyOfValue,
+ typename _Compare, typename _Alloc>
+ 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <map>
+
+struct A { A(A&&) = delete; };
+
+void test01()
+{
+ std::map<int, A> m1, m2;
+ m2 = std::move(m1);
+}