summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-02-11 11:59:44 +0000
committerEric Fiselier <eric@efcs.ca>2016-02-11 11:59:44 +0000
commitfcd0221118a51dbfb812245b13b881971983d92e (patch)
treea445b7f8a7a224136567fac184b39827838fba48 /libcxx/test/std
parent62498ff8f5fa0e232e33da9cb7a9aa86b51c40f9 (diff)
downloadbcm5719-llvm-fcd0221118a51dbfb812245b13b881971983d92e.tar.gz
bcm5719-llvm-fcd0221118a51dbfb812245b13b881971983d92e.zip
Teach __hash_table how to handle unordered_map's __hash_value_type.
This patch is fairly large and contains a number of changes. The main change is teaching '__hash_table' how to handle '__hash_value_type'. Unfortunately this change is a rampant layering violation, but it's required to make unordered_map conforming without re-writing all of __hash_table. After this change 'unordered_map' can delegate to '__hash_table' in almost all cases. The major changes found in this patch are: * Teach __hash_table to differentiate between the true container value type and the node value type by introducing the "__container_value_type" and "__node_value_type" typedefs. In the case of unordered_map '__container_value_type' is 'pair<const Key, Value>' and '__node_value_type' is '__hash_value_type'. * Switch almost all overloads in '__hash_table' previously taking 'value_type' (AKA '__node_value_type) to take '__container_value_type' instead. Previously 'pair<K, V>' would be implicitly converted to '__hash_value_type<K, V>' because of the function signature. * Add '__get_key', '__get_value', '__get_ptr', and '__move' static functions to '__key_value_types'. These functions allow '__hash_table' to unwrap '__node_value_type' objects into '__container_value_type' and its sub-parts. * Pass '__hash_value_type::__value_' to 'a.construct(p, ...)' instead of '__hash_value_type' itself. The C++14 standard requires that 'a.construct()' and 'a.destroy()' are only ever instantiated for the containers value type. * Remove '__hash_value_type's constructors and destructors. We should never construct an instance of this type. (TODO this is UB but we already do it in plenty of places). * Add a generic "try-emplace" function to '__hash_table' called '__emplace_unique_key_args(Key const&, Args...)'. The following changes were done as cleanup: * Introduce the '_LIBCPP_CXX03_LANG' macro to be used in place of '_LIBCPP_HAS_NO_VARIADICS' or '_LIBCPP_HAS_NO_RVALUE_REFERENCE'. * Cleanup C++11 only overloads that assume an incomplete C++11 implementation. For example this patch removes the __construct_node overloads that do manual pack expansion. * Forward 'unordered_map::emplace' to '__hash_table' and remove dead code resulting from the change. This includes almost all 'unordered_map::__construct_node' overloads. The following changes are planed for future revisions: * Fix LWG issue #2469 by delegating 'unordered_map::operator[]' to use '__emplace_unique_key_args'. * Rewrite 'unordered_map::try_emplace' in terms of '__emplace_unique_key_args'. * Optimize '__emplace_unique' to call '__emplace_unique_key_args' when possible. This prevent unneeded allocations when inserting duplicate entries. The additional follow up work needed after this patch: * Respect the lifetime rules for '__hash_value_type' by actually constructing it. * Make '__insert_multi' act similar to '__insert_unique' for objects of type 'T&' and 'T const &&' with 'T = __container_value_type'. llvm-svn: 260513
Diffstat (limited to 'libcxx/test/std')
-rw-r--r--libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp143
-rw-r--r--libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_allocator_requirements.pass.cpp108
-rw-r--r--libcxx/test/std/containers/unord/unord.multiset/insert_allocator_requirements.pass.cpp107
-rw-r--r--libcxx/test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp142
4 files changed, 500 insertions, 0 deletions
diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp
new file mode 100644
index 00000000000..e889ce33480
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <unordered_map>
+
+// class unordered_map
+
+// insert(...);
+
+// UNSUPPORTED: c++98, c++03
+
+
+#include <unordered_map>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+#if TEST_STD_VER >= 11
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+#else
+template <class Arg>
+void PrintInfo(int line, Arg arg)
+#endif
+{
+ std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
+}
+#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
+
+template <class Container>
+void testContainerInsert()
+{
+ typedef typename Container::value_type ValueTp;
+ typedef Container C;
+ typedef std::pair<typename C::iterator, bool> R;
+ ConstructController* cc = getConstructController();
+ cc->reset();
+ {
+ PRINT("Testing C::insert(const value_type&)");
+ Container c;
+ const ValueTp v(42, 1);
+ cc->expect<const ValueTp&>();
+ assert(c.insert(v).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ const ValueTp v2(42, 1);
+ assert(c.insert(v2).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(value_type&)");
+ Container c;
+ ValueTp v(42, 1);
+ cc->expect<const ValueTp&>();
+ assert(c.insert(v).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp v2(42, 1);
+ assert(c.insert(v2).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(value_type&&)");
+ Container c;
+ ValueTp v(42, 1);
+ cc->expect<ValueTp&&>();
+ assert(c.insert(std::move(v)).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp v2(42, 1);
+ assert(c.insert(std::move(v2)).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+ Container c;
+ std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
+ cc->expect<ValueTp const&>(2);
+ c.insert(il);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(il);
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+ Container c;
+ const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+ cc->expect<ValueTp&&>(3);
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+ std::move_iterator<ValueTp*>(std::end(ValueList)));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp ValueList2[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
+ std::move_iterator<ValueTp*>(std::end(ValueList2)));
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ }
+ }
+}
+
+
+int main()
+{
+ testContainerInsert<TCT::unordered_map<> >();
+}
diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_allocator_requirements.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_allocator_requirements.pass.cpp
new file mode 100644
index 00000000000..0926e8057ca
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_allocator_requirements.pass.cpp
@@ -0,0 +1,108 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <unordered_map>
+
+// class unordered_multimap
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <unordered_map>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+#if TEST_STD_VER >= 11
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+#else
+template <class Arg>
+void PrintInfo(int line, Arg arg)
+#endif
+{
+ std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
+}
+#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
+
+template <class Container>
+void testContainerInsert()
+{
+ typedef typename Container::value_type ValueTp;
+ typedef Container C;
+ ConstructController* cc = getConstructController();
+ cc->reset();
+ {
+ PRINT("Testing C::insert(const value_type&)");
+ Container c;
+ const ValueTp v(42, 1);
+ cc->expect<const ValueTp&>();
+ c.insert(v);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(value_type&)");
+ Container c;
+ ValueTp v(42, 1);
+ cc->expect<ValueTp&>();
+ c.insert(v);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(value_type&&)");
+ Container c;
+ ValueTp v(42, 1);
+ cc->expect<ValueTp&&>();
+ c.insert(std::move(v));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+ Container c;
+ std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
+ cc->expect<ValueTp const&>(2);
+ c.insert(il);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+ Container c;
+ const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+ cc->expect<ValueTp&&>(3);
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+ std::move_iterator<ValueTp*>(std::end(ValueList)));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
+ cc->expect<ValueTp&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ }
+}
+
+
+int main()
+{
+ testContainerInsert<TCT::unordered_multimap<> >();
+}
diff --git a/libcxx/test/std/containers/unord/unord.multiset/insert_allocator_requirements.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/insert_allocator_requirements.pass.cpp
new file mode 100644
index 00000000000..ae8ce055910
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multiset/insert_allocator_requirements.pass.cpp
@@ -0,0 +1,107 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <unordered_set>
+
+// class unordered_multiset
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <unordered_set>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+#if TEST_STD_VER >= 11
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+#else
+template <class Arg>
+void PrintInfo(int line, Arg arg)
+#endif
+{
+ std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
+}
+#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
+
+template <class Container>
+void testContainerInsert()
+{
+ typedef typename Container::value_type ValueTp;
+ typedef Container C;
+ ConstructController* cc = getConstructController();
+ cc->reset();
+ {
+ PRINT("Testing C::insert(const value_type&)");
+ Container c;
+ const ValueTp v(42);
+ cc->expect<const ValueTp&>();
+ c.insert(v);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(value_type&)");
+ Container c;
+ ValueTp v(42);
+ cc->expect<const ValueTp&>();
+ c.insert(v);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(value_type&&)");
+ Container c;
+ ValueTp v(42);
+ cc->expect<ValueTp&&>();
+ c.insert(std::move(v));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+ Container c;
+ std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
+ cc->expect<ValueTp const&>(2);
+ c.insert(il);
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+ Container c;
+ const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+ cc->expect<ValueTp&&>(3);
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+ std::move_iterator<ValueTp*>(std::end(ValueList)));
+ assert(!cc->unchecked());
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+ cc->expect<ValueTp&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ }
+}
+
+int main()
+{
+ testContainerInsert<TCT::unordered_multiset<> >();
+}
diff --git a/libcxx/test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp b/libcxx/test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp
new file mode 100644
index 00000000000..f5a30c237b9
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp
@@ -0,0 +1,142 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <unordered_set>
+
+// class unordered_set
+
+// insert(...)
+
+// UNSUPPORTED: c++98, c++03
+
+#include <unordered_set>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "container_test_types.h"
+
+#if TEST_STD_VER >= 11
+template <class Arg>
+void PrintInfo(int line, Arg&& arg)
+#else
+template <class Arg>
+void PrintInfo(int line, Arg arg)
+#endif
+{
+ std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
+}
+#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
+
+template <class Container>
+void testContainerInsert()
+{
+ typedef typename Container::value_type ValueTp;
+ typedef Container C;
+ typedef std::pair<typename C::iterator, bool> R;
+ ConstructController* cc = getConstructController();
+ cc->reset();
+ {
+ PRINT("Testing C::insert(const value_type&)");
+ Container c;
+ const ValueTp v(42);
+ cc->expect<const ValueTp&>();
+ assert(c.insert(v).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ const ValueTp v2(42);
+ assert(c.insert(v2).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(value_type&)");
+ Container c;
+ ValueTp v(42);
+ cc->expect<const ValueTp&>();
+ assert(c.insert(v).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp v2(42);
+ assert(c.insert(v2).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(value_type&&)");
+ Container c;
+ ValueTp v(42);
+ cc->expect<ValueTp&&>();
+ assert(c.insert(std::move(v)).second);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp v2(42);
+ assert(c.insert(std::move(v2)).second == false);
+ }
+ }
+ {
+ PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
+ Container c;
+ std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
+ cc->expect<ValueTp const&>(2);
+ c.insert(il);
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(il);
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
+ Container c;
+ const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+ cc->expect<ValueTp&&>(3);
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
+ std::move_iterator<ValueTp*>(std::end(ValueList)));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ ValueTp ValueList2[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+ c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
+ std::move_iterator<ValueTp*>(std::end(ValueList2)));
+ }
+ }
+ {
+ PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
+ Container c;
+ ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
+ cc->expect<ValueTp const&>(3);
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ assert(!cc->unchecked());
+ {
+ DisableAllocationGuard g;
+ c.insert(std::begin(ValueList), std::end(ValueList));
+ }
+ }
+}
+
+
+int main()
+{
+ testContainerInsert<TCT::unordered_set<> >();
+}
OpenPOWER on IntegriCloud