diff options
author | fdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-11-28 06:27:28 +0000 |
---|---|---|
committer | fdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-11-28 06:27:28 +0000 |
commit | d7db240c78745e107bb1fdfb5fe6ed72f39c94ec (patch) | |
tree | 118ff510ba13bb0d3fba9cb1c74a7f0e99f6bb9f /libstdc++-v3 | |
parent | 4822b190bceca7b6535dccbda127e87c20446423 (diff) |
2018-11-28 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/88199
* include/bits/hashtable.h
(_Hashtable<>::_M_move_assign(_Hashtable&&, false_type)): Deallocate
former buckets after assignment.
* testsuite/23_containers/unordered_set/allocator/move_assign.cc
(test03): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-8-branch@266543 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/hashtable.h | 3 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc | 128 |
3 files changed, 107 insertions, 33 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a92c245c392..5056578e265 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2018-11-28 François Dumont <fdumont@gcc.gnu.org> + + PR libstdc++/88199 + * include/bits/hashtable.h + (_Hashtable<>::_M_move_assign(_Hashtable&&, false_type)): Deallocate + former buckets after assignment. + * testsuite/23_containers/unordered_set/allocator/move_assign.cc + (test03): New. + 2018-11-22 Jonathan Wakely <jwakely@redhat.com> Backport from mainline diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index af16e2c03cb..ba1d35dbecf 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -1222,6 +1222,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_assign(__ht, [&__roan](__node_type* __n) { return __roan(std::move_if_noexcept(__n->_M_v())); }); + + if (__former_buckets) + _M_deallocate_buckets(__former_buckets, __former_bucket_count); __ht.clear(); } __catch(...) diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc index ef6c0deb1af..3a553897581 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc @@ -18,71 +18,133 @@ // { dg-do run { target c++11 } } #include <unordered_set> + #include <testsuite_hooks.h> #include <testsuite_allocator.h> #include <testsuite_counter_type.h> using __gnu_test::propagating_allocator; using __gnu_test::counter_type; +using __gnu_test::tracker_allocator; +using __gnu_test::tracker_allocator_counter; void test01() { - typedef propagating_allocator<counter_type, false> alloc_type; - typedef __gnu_test::counter_type_hasher hash; - typedef std::unordered_set<counter_type, hash, - std::equal_to<counter_type>, - alloc_type> test_type; + tracker_allocator_counter::reset(); + { + typedef propagating_allocator<counter_type, false, + tracker_allocator<counter_type>> alloc_type; + typedef __gnu_test::counter_type_hasher hash; + typedef std::unordered_set<counter_type, hash, + std::equal_to<counter_type>, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.emplace(0); - test_type v1(alloc_type(1)); - v1.emplace(0); + test_type v2(alloc_type(2)); + v2.emplace(1); - test_type v2(alloc_type(2)); - v2.emplace(1); + counter_type::reset(); - counter_type::reset(); + v2 = std::move(v1); - v2 = std::move(v1); + VERIFY( 1 == v1.get_allocator().get_personality() ); + VERIFY( 2 == v2.get_allocator().get_personality() ); - VERIFY( 1 == v1.get_allocator().get_personality() ); - VERIFY( 2 == v2.get_allocator().get_personality() ); + VERIFY( counter_type::move_count == 1 ); + VERIFY( counter_type::destructor_count == 2 ); + } - VERIFY( counter_type::move_count == 1 ); - VERIFY( counter_type::destructor_count == 2 ); + // Check there's nothing left allocated or constructed. + VERIFY( tracker_allocator_counter::get_construct_count() + == tracker_allocator_counter::get_destruct_count() ); + VERIFY( tracker_allocator_counter::get_allocation_count() + == tracker_allocator_counter::get_deallocation_count() ); } void test02() { - typedef propagating_allocator<counter_type, true> alloc_type; - typedef __gnu_test::counter_type_hasher hash; - typedef std::unordered_set<counter_type, hash, - std::equal_to<counter_type>, - alloc_type> test_type; + tracker_allocator_counter::reset(); + { + typedef propagating_allocator<counter_type, true, + tracker_allocator<counter_type>> alloc_type; + typedef __gnu_test::counter_type_hasher hash; + typedef std::unordered_set<counter_type, hash, + std::equal_to<counter_type>, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.emplace(0); - test_type v1(alloc_type(1)); - v1.emplace(0); + auto it = v1.begin(); - auto it = v1.begin(); + test_type v2(alloc_type(2)); + v2.emplace(0); - test_type v2(alloc_type(2)); - v2.emplace(0); + counter_type::reset(); - counter_type::reset(); + v2 = std::move(v1); - v2 = std::move(v1); + VERIFY(0 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); - VERIFY(0 == v1.get_allocator().get_personality()); - VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( counter_type::move_count == 0 ); + VERIFY( counter_type::copy_count == 0 ); + VERIFY( counter_type::destructor_count == 1 ); - VERIFY( counter_type::move_count == 0 ); - VERIFY( counter_type::copy_count == 0 ); - VERIFY( counter_type::destructor_count == 1 ); + VERIFY( it == v2.begin() ); + } - VERIFY( it == v2.begin() ); + // Check there's nothing left allocated or constructed. + VERIFY( tracker_allocator_counter::get_construct_count() + == tracker_allocator_counter::get_destruct_count() ); + VERIFY( tracker_allocator_counter::get_allocation_count() + == tracker_allocator_counter::get_deallocation_count() ); +} + +void test03() +{ + tracker_allocator_counter::reset(); + { + typedef propagating_allocator<counter_type, false, + tracker_allocator<counter_type>> alloc_type; + typedef __gnu_test::counter_type_hasher hash; + typedef std::unordered_set<counter_type, hash, + std::equal_to<counter_type>, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.emplace(0); + + test_type v2(alloc_type(2)); + int i = 0; + v2.emplace(i++); + for (; v2.bucket_count() == v1.bucket_count(); ++i) + v2.emplace(i); + + counter_type::reset(); + + v2 = std::move(v1); + + VERIFY( 1 == v1.get_allocator().get_personality() ); + VERIFY( 2 == v2.get_allocator().get_personality() ); + + VERIFY( counter_type::move_count == 1 ); + VERIFY( counter_type::destructor_count == i + 1 ); + } + + // Check there's nothing left allocated or constructed. + VERIFY( tracker_allocator_counter::get_construct_count() + == tracker_allocator_counter::get_destruct_count() ); + VERIFY( tracker_allocator_counter::get_allocation_count() + == tracker_allocator_counter::get_deallocation_count() ); } int main() { test01(); test02(); + test03(); return 0; } |