From 8cab3d18f0fc520829687383e8f050c7442e7fe0 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 22 Jul 2016 16:03:11 +0100 Subject: [PATCH] Move allocator in std::string and RB tree move constructors PR libstdc++/71964 * include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI] (basic_string::_Alloc_hider(pointer, _Alloc&&)): Add constructor. * include/bits/stl_tree.h (_Rb_tree(_Rb_tree&&)): Move allocator. * testsuite/21_strings/basic_string/allocator/71964.cc: New test. * testsuite/23_containers/set/allocator/71964.cc: New test. From-SVN: r238647 --- libstdc++-v3/ChangeLog | 7 ++ libstdc++-v3/include/bits/basic_string.h | 8 ++ libstdc++-v3/include/bits/stl_tree.h | 3 +- .../basic_string/allocator/71964.cc | 74 +++++++++++++++++++ .../23_containers/set/allocator/71964.cc | 71 ++++++++++++++++++ 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc create mode 100644 libstdc++-v3/testsuite/23_containers/set/allocator/71964.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3698ded5307..3f5d6b07814 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2016-07-22 Jonathan Wakely + PR libstdc++/71964 + * include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI] + (basic_string::_Alloc_hider(pointer, _Alloc&&)): Add constructor. + * include/bits/stl_tree.h (_Rb_tree(_Rb_tree&&)): Move allocator. + * testsuite/21_strings/basic_string/allocator/71964.cc: New test. + * testsuite/23_containers/set/allocator/71964.cc: New test. + * testsuite/lib/libstdc++.exp (check_v3_target_namedlocale): Use delete[] instead of delete. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 60e1dbfb5cc..58d6e4d4e3a 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -106,8 +106,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html struct _Alloc_hider : allocator_type // TODO check __is_final { +#if __cplusplus < 201103L _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc()) : allocator_type(__a), _M_p(__dat) { } +#else + _Alloc_hider(pointer __dat, const _Alloc& __a) + : allocator_type(__a), _M_p(__dat) { } + + _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc()) + : allocator_type(std::move(__a)), _M_p(__dat) { } +#endif pointer _M_p; // The actual data. }; diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index a9ca3facf99..7a9a4a6c277 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -851,7 +851,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _Rb_tree(_Rb_tree&& __x) - : _M_impl(__x._M_impl._M_key_compare, __x._M_get_Node_allocator()) + : _M_impl(__x._M_impl._M_key_compare, + std::move(__x._M_get_Node_allocator())) { if (__x._M_root() != 0) _M_move_data(__x, std::true_type()); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc new file mode 100644 index 00000000000..ebb66cfc7bf --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc @@ -0,0 +1,74 @@ +// 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-options "-std=gnu++11" } + +#include +#include + +template + struct mv_allocator + { + using value_type = T; + using size_type = unsigned; + + mv_allocator() + : moved_to(false), moved_from(false) { } + + template + mv_allocator(const mv_allocator & a) + : moved_to(a.moved_to), moved_from(a.moved_from) { } + + mv_allocator(const mv_allocator &) = default; + + mv_allocator(mv_allocator && a) noexcept : moved_to(true) + { + a.moved_from = true; + } + + T* allocate(unsigned n) { return std::allocator{}.allcoate(n); } + void deallocate(T* p, unsigned n) { std::allocator{}.deallocate(p, n); } + + bool moved_to; + bool moved_from; + }; + +template +bool +operator==(const mv_allocator&, const mv_allocator&) { return true; } + +template +bool +operator!=(const mv_allocator&, const mv_allocator&) { return false; } + +void +test01() +{ + // COW strings don't support C++11 allocators +#if _GLIBCXX_USE_CXX11_ABI + std::basic_string, mv_allocator> s; + auto t = std::move(s); + VERIFY( s.get_allocator().moved_from ); + VERIFY( t.get_allocator().moved_to ); +#endif +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/23_containers/set/allocator/71964.cc b/libstdc++-v3/testsuite/23_containers/set/allocator/71964.cc new file mode 100644 index 00000000000..f13828feffd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/set/allocator/71964.cc @@ -0,0 +1,71 @@ +// 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-options "-std=gnu++11" } + +#include +#include + +template + struct mv_allocator + { + using value_type = T; + using size_type = unsigned; + + mv_allocator() + : moved_to(false), moved_from(false) { } + + template + mv_allocator(const mv_allocator & a) + : moved_to(a.moved_to), moved_from(a.moved_from) { } + + mv_allocator(const mv_allocator &) = default; + + mv_allocator(mv_allocator && a) noexcept : moved_to(true) + { + a.moved_from = true; + } + + T* allocate(unsigned n) { return std::allocator{}.allcoate(n); } + void deallocate(T* p, unsigned n) { std::allocator{}.deallocate(p, n); } + + bool moved_to; + bool moved_from; + }; + +template +bool +operator==(const mv_allocator&, const mv_allocator&) { return true; } + +template +bool +operator!=(const mv_allocator&, const mv_allocator&) { return false; } + +void +test01() +{ + std::set, mv_allocator> s; + auto t = std::move(s); + VERIFY( s.get_allocator().moved_from ); + VERIFY( t.get_allocator().moved_to ); +} + +int +main() +{ + test01(); +}