dexonsmith updated this revision to Diff 47936.
dexonsmith added a comment.
Updated the patch to apply against r260513. The logic is much simpler now;
thanks Eric for the cleanup.
Let me know if there's anything else to do!
http://reviews.llvm.org/D16360
Files:
include/__hash_table
test/libcxx/containers/unord/unord.map/insert_dup_alloc.pass.cpp
Index: test/libcxx/containers/unord/unord.map/insert_dup_alloc.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/containers/unord/unord.map/insert_dup_alloc.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// Check that we don't allocate when trying to insert a duplicate value into a
+// unordered_map.
+
+#include <cassert>
+#include <unordered_map>
+#include "count_new.hpp"
+#include "MoveOnly.h"
+
+int main() {
+ {
+ std::unordered_map<int, int> s;
+ assert(globalMemCounter.checkNewCalledEq(0));
+
+ for (int i = 0; i < 100; ++i) {
+ std::pair<const int, int> P(3, i);
+ s.insert(P);
+ s.insert(std::make_pair(3, i));
+ s.insert(std::make_pair(3, unsigned(i)));
+ s.insert(s.end(), std::make_pair(3, i));
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+ s.emplace(std::make_pair(3, i));
+ s.emplace_hint(s.end(), std::make_pair(3, i));
+#endif
+ {
+ const std::pair<int, int> P(3, i);
+ s.insert(P);
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+ s.emplace(P);
+ s.emplace_hint(s.end(), P);
+#endif
+ }
+ }
+
+ assert(s.size() == 1);
+ assert(s.count(3) == 1);
+ assert(s.at(3) == 0);
+ assert(globalMemCounter.checkNewCalledEq(2));
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ globalMemCounter.reset();
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+ {
+ std::unordered_map<MoveOnly, MoveOnly> s;
+ assert(globalMemCounter.checkNewCalledEq(0));
+
+ for (int i = 0; i < 100; i++) {
+ s.insert(std::make_pair(MoveOnly(3), MoveOnly(i)));
+ s.insert(s.end(), std::make_pair(MoveOnly(3), MoveOnly(i)));
+ s.emplace(std::make_pair(MoveOnly(3), MoveOnly(i)));
+ s.emplace_hint(s.end(), std::make_pair(MoveOnly(3), MoveOnly(i)));
+ }
+
+ assert(s.size() == 1);
+ assert(s.count(MoveOnly(3)) == 1);
+ assert(s.at(MoveOnly(3)) == 0);
+ assert(globalMemCounter.checkNewCalledEq(2));
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ globalMemCounter.reset();
+ {
+ std::unordered_map<int, MoveOnly> s;
+ assert(globalMemCounter.checkNewCalledEq(0));
+
+ for (int i = 0; i < 100; i++) {
+ s.insert(std::make_pair(3, MoveOnly(i)));
+ s.insert(s.end(), std::make_pair(3, MoveOnly(i)));
+ s.emplace(std::make_pair(3, MoveOnly(i)));
+ s.emplace_hint(s.end(), std::make_pair(3, MoveOnly(i)));
+ }
+
+ assert(s.size() == 1);
+ assert(s.count(3) == 1);
+ assert(s.at(3) == 0);
+ assert(globalMemCounter.checkNewCalledEq(2));
+ }
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ globalMemCounter.reset();
+#endif
+}
Index: include/__hash_table
===================================================================
--- include/__hash_table
+++ include/__hash_table
@@ -100,6 +100,14 @@
return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
}
+template <class _Pair, class _Key,
+ class _RawPair = typename __uncvref<_Pair>::type>
+struct __is_pair_with_key : false_type {};
+
+template <class _Pair, class _Key, class _First, class _Second>
+struct __is_pair_with_key<_Pair, _Key, pair<_First, _Second>>
+ : is_same<typename remove_const<_First>::type, _Key> {};
+
template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_iterator;
@@ -901,6 +909,7 @@
typedef typename _NodeTypes::__node_value_type __node_value_type;
typedef typename _NodeTypes::__container_value_type __container_value_type;
+ typedef typename _NodeTypes::key_type key_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename __alloc_traits::pointer pointer;
@@ -1039,13 +1048,41 @@
#ifndef _LIBCPP_CXX03_LANG
template <class _Key, class ..._Args>
+ _LIBCPP_INLINE_VISIBILITY
pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
template <class... _Args>
- pair<iterator, bool> __emplace_unique(_Args&&... __args);
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
+
+ template <class _Pp>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> __emplace_unique(_Pp&& __x) {
+ return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x),
+ __is_pair_with_key<_Pp, key_type>());
+ }
template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> __emplace_unique(_Args&&... __args) {
+ return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...);
+ }
+
+ template <class _Pp>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, false_type) {
+ return __emplace_unique_impl(_VSTD::forward<_Pp>(__x));
+ }
+ template <class _Pp>
+ _LIBCPP_INLINE_VISIBILITY
+ pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, true_type) {
+ return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x));
+ }
+
+ template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
iterator __emplace_multi(_Args&&... __args);
template <class... _Args>
+ _LIBCPP_INLINE_VISIBILITY
iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
@@ -1987,7 +2024,7 @@
template <class _Tp, class _Hash, class _Equal, class _Alloc>
template <class... _Args>
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
-__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
+__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args)
{
__node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
pair<iterator, bool> __r = __node_insert_unique(__h.get());
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits