aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorfdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4>2018-11-28 06:27:28 +0000
committerfdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4>2018-11-28 06:27:28 +0000
commitd7db240c78745e107bb1fdfb5fe6ed72f39c94ec (patch)
tree118ff510ba13bb0d3fba9cb1c74a7f0e99f6bb9f /libstdc++-v3
parent4822b190bceca7b6535dccbda127e87c20446423 (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/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/hashtable.h3
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc128
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;
}