summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-02-10 20:46:23 +0000
committerEric Fiselier <eric@efcs.ca>2016-02-10 20:46:23 +0000
commit774c7c5ca8c3d224830bcd9a23c7d9ae52b91bcd (patch)
tree1985be7ab9cdf333cdf911bd62287f29be0287ad
parentf8865b62c38f744c845389567eed0a98e8c88d97 (diff)
downloadexternal_libcxx-774c7c5ca8c3d224830bcd9a23c7d9ae52b91bcd.tar.gz
external_libcxx-774c7c5ca8c3d224830bcd9a23c7d9ae52b91bcd.tar.bz2
external_libcxx-774c7c5ca8c3d224830bcd9a23c7d9ae52b91bcd.zip
Recommit r260012 - Cleanup node-type handling in the unordered containers.
This time I kept <ext/hash_map> working! This patch is the first in a series of patches that's meant to better support unordered_map. unordered_map has a special "value_type" that differs from pair<const Key, Value>. In order to meet the EmplaceConstructible and CopyInsertable requirements we need to teach __hash_table about this special value_type. This patch creates a "__hash_node_types" traits class that contains all of the typedefs needed by the unordered containers and it's iterators. These typedefs include ones for each node type and node pointer type, as well as special typedefs for "unordered_map"'s value type. As a result of this change all of the unordered containers now all support incomplete types. As a drive-by fix I changed the difference_type in __hash_table to always be ptrdiff_t. There is a corresponding change to size_type but it cannot take affect until an ABI break. This patch will be followed up shortly with fixes for various unordered_map bugs and problems. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@260431 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/__config1
-rw-r--r--include/__hash_table218
-rw-r--r--include/ext/hash_map2
-rw-r--r--include/unordered_map47
-rw-r--r--test/libcxx/containers/unord/key_value_traits.pass.cpp59
-rw-r--r--test/std/containers/unord/iterator_difference_type.pass.cpp154
-rw-r--r--test/std/containers/unord/unord.map/incomplete_type.pass.cpp37
-rw-r--r--test/std/containers/unord/unord.multimap/incomplete.pass.cpp37
-rw-r--r--test/std/containers/unord/unord.multiset/incomplete.pass.cpp38
-rw-r--r--test/std/containers/unord/unord.set/incomplete.pass.cpp38
10 files changed, 559 insertions, 72 deletions
diff --git a/include/__config b/include/__config
index 83e6e2a5d..592166297 100644
--- a/include/__config
+++ b/include/__config
@@ -42,6 +42,7 @@
// Fix undefined behavior in how std::list stores it's linked nodes.
#define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
#define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
+#define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
#endif
#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
diff --git a/include/__hash_table b/include/__hash_table
index c48e38376..5f21de4ce 100644
--- a/include/__hash_table
+++ b/include/__hash_table
@@ -17,6 +17,7 @@
#include <iterator>
#include <algorithm>
#include <cmath>
+#include <utility>
#include <__undef_min_max>
#include <__undef___deallocate>
@@ -49,10 +50,10 @@ struct __hash_node
typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type
>
{
- typedef _Tp value_type;
+ typedef _Tp __node_value_type;
size_t __hash_;
- value_type __value_;
+ __node_value_type __value_;
};
inline _LIBCPP_INLINE_VISIBILITY
@@ -77,23 +78,126 @@ __next_hash_pow2(size_t __n)
}
template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
+
+template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_iterator;
template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator;
+template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator;
+template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator;
template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator;
template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator;
+#if __cplusplus >= 201103L
+template <class _Key, class _Tp>
+union __hash_value_type;
+#else
+template <class _Key, class _Tp>
+struct __hash_value_type;
+#endif
+
+template <class _Tp>
+struct __key_value_types {
+ static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
+ typedef _Tp key_type;
+ typedef _Tp __node_value_type;
+ typedef _Tp __container_value_type;
+ static const bool __is_map = false;
+};
+
+template <class _Key, class _Tp>
+struct __key_value_types<__hash_value_type<_Key, _Tp> > {
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef __hash_value_type<_Key, _Tp> __node_value_type;
+ typedef pair<const _Key, _Tp> __container_value_type;
+ typedef __container_value_type __map_value_type;
+ static const bool __is_map = true;
+};
+
+template <class _Tp, class _AllocPtr, class _KVTypes = __key_value_types<_Tp>,
+ bool = _KVTypes::__is_map>
+struct __map_pointer_types {};
+
+template <class _Tp, class _AllocPtr, class _KVTypes>
+struct __map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
+ typedef typename _KVTypes::__map_value_type _Mv;
+ typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
+ __map_value_type_pointer;
+ typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
+ __const_map_value_type_pointer;
+};
+
+template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
+struct __hash_node_types;
+
+template <class _NodePtr, class _Tp, class _VoidPtr>
+struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
+ : public __key_value_types<_Tp>, __map_pointer_types<_Tp, _VoidPtr>
+
+{
+ typedef __key_value_types<_Tp> __base;
+
+public:
+ typedef ptrdiff_t difference_type;
+ typedef size_t size_type;
+
+ typedef typename __rebind_pointer<_NodePtr, void>::type __void_pointer;
+
+ typedef typename pointer_traits<_NodePtr>::element_type __node_type;
+ typedef _NodePtr __node_pointer;
+
+ typedef __hash_node_base<__node_pointer> __node_base_type;
+ typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type
+ __node_base_pointer;
+
+ typedef _Tp __node_value_type;
+ typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
+ __node_value_type_pointer;
+ typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
+ __const_node_value_type_pointer;
+private:
+ static_assert(!is_const<__node_type>::value,
+ "_NodePtr should never be a pointer to const");
+ static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
+ "_VoidPtr does not point to unqualified void type");
+ static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
+ _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
+};
+
+
+
+template <class _HashIterator>
+struct __hash_node_types_from_iterator;
+template <class _NodePtr>
+struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
+template <class _NodePtr>
+struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
+template <class _NodePtr>
+struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
+template <class _NodePtr>
+struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
+
+
+template <class _NodeValueTp, class _VoidPtr>
+struct __make_hash_node_types {
+ typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
+ typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr;
+ typedef __hash_node_types<_NodePtr> type;
+};
+
template <class _NodePtr>
class _LIBCPP_TYPE_VIS_ONLY __hash_iterator
{
- typedef _NodePtr __node_pointer;
+ typedef __hash_node_types<_NodePtr> _NodeTypes;
+ typedef _NodePtr __node_pointer;
__node_pointer __node_;
public:
- typedef forward_iterator_tag iterator_category;
- typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
- typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
- typedef value_type& reference;
- typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer;
+ typedef forward_iterator_tag iterator_category;
+ typedef typename _NodeTypes::__node_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
+ typedef value_type& reference;
+ typedef typename _NodeTypes::__node_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT
#if _LIBCPP_STD_VER > 11
@@ -202,25 +306,22 @@ private:
template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap;
};
-template <class _ConstNodePtr>
+template <class _NodePtr>
class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator
{
- typedef _ConstNodePtr __node_pointer;
-
- __node_pointer __node_;
-
- typedef typename remove_const<
- typename pointer_traits<__node_pointer>::element_type
- >::type __node;
+ static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
+ typedef __hash_node_types<_NodePtr> _NodeTypes;
+ typedef _NodePtr __node_pointer;
+ typedef __hash_iterator<_NodePtr> __non_const_iterator;
+ __node_pointer __node_;
public:
- typedef forward_iterator_tag iterator_category;
- typedef typename __node::value_type value_type;
- typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
- typedef const value_type& reference;
- typedef typename __rebind_pointer<__node_pointer, const value_type>::type pointer;
- typedef typename __rebind_pointer<__node_pointer, __node>::type __non_const_node_pointer;
- typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
+ typedef forward_iterator_tag iterator_category;
+ typedef typename _NodeTypes::__node_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
+ typedef const value_type& reference;
+ typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
+
_LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT
#if _LIBCPP_STD_VER > 11
@@ -336,24 +437,22 @@ private:
template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap;
};
-template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator;
-
template <class _NodePtr>
class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator
{
- typedef _NodePtr __node_pointer;
+ typedef __hash_node_types<_NodePtr> _NodeTypes;
+ typedef _NodePtr __node_pointer;
__node_pointer __node_;
size_t __bucket_;
size_t __bucket_count_;
- typedef pointer_traits<__node_pointer> __pointer_traits;
public:
typedef forward_iterator_tag iterator_category;
- typedef typename __pointer_traits::element_type::value_type value_type;
- typedef typename __pointer_traits::difference_type difference_type;
+ typedef typename _NodeTypes::__node_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
typedef value_type& reference;
- typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer;
+ typedef typename _NodeTypes::__node_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT
{
@@ -476,7 +575,8 @@ private:
template <class _ConstNodePtr>
class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator
{
- typedef _ConstNodePtr __node_pointer;
+ typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
+ typedef _ConstNodePtr __node_pointer;
__node_pointer __node_;
size_t __bucket_;
@@ -491,14 +591,11 @@ class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator
typedef __hash_local_iterator<__non_const_node_pointer>
__non_const_iterator;
public:
- typedef forward_iterator_tag iterator_category;
- typedef typename remove_const<
- typename __pointer_traits::element_type::value_type
- >::type value_type;
- typedef typename __pointer_traits::difference_type difference_type;
- typedef const value_type& reference;
- typedef typename __rebind_pointer<__node_pointer, const value_type>::type
- pointer;
+ typedef forward_iterator_tag iterator_category;
+ typedef typename _NodeTypes::__node_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
+ typedef const value_type& reference;
+ typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT
@@ -686,7 +783,7 @@ class __hash_node_destructor
{
typedef _Alloc allocator_type;
typedef allocator_traits<allocator_type> __alloc_traits;
- typedef typename __alloc_traits::value_type::value_type value_type;
+
public:
typedef typename __alloc_traits::pointer pointer;
private:
@@ -728,23 +825,42 @@ public:
private:
typedef allocator_traits<allocator_type> __alloc_traits;
+ typedef typename
+ __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type
+ _NodeTypes;
public:
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename __alloc_traits::pointer pointer;
typedef typename __alloc_traits::const_pointer const_pointer;
+#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
typedef typename __alloc_traits::size_type size_type;
- typedef typename __alloc_traits::difference_type difference_type;
+#else
+ typedef typename _NodeTypes::size_type size_type;
+#endif
+ typedef typename _NodeTypes::difference_type difference_type;
public:
// Create __node
- typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
+
+ typedef typename _NodeTypes::__node_type __node;
typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
typedef allocator_traits<__node_allocator> __node_traits;
- typedef typename __node_traits::pointer __node_pointer;
- typedef typename __node_traits::pointer __node_const_pointer;
- typedef __hash_node_base<__node_pointer> __first_node;
- typedef typename __rebind_pointer<__node_pointer, __first_node>::type
- __node_base_pointer;
+ typedef typename _NodeTypes::__node_pointer __node_pointer;
+ typedef typename _NodeTypes::__node_pointer __node_const_pointer;
+ typedef typename _NodeTypes::__node_base_type __first_node;
+ typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
+
+private:
+ // check for sane allocator pointer rebinding semantics. Rebinding the
+ // allocator for a new pointer type should be exactly the same as rebinding
+ // the pointer using 'pointer_traits'.
+ static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
+ "Allocator does not rebind pointers in a sane manner.");
+ typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type
+ __node_base_allocator;
+ typedef allocator_traits<__node_base_allocator> __node_base_traits;
+ static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
+ "Allocator does not rebind pointers in a sane manner.");
private:
@@ -755,10 +871,10 @@ private:
typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
// --- Member data begin ---
- __bucket_list __bucket_list_;
- __compressed_pair<__first_node, __node_allocator> __p1_;
- __compressed_pair<size_type, hasher> __p2_;
- __compressed_pair<float, key_equal> __p3_;
+ __bucket_list __bucket_list_;
+ __compressed_pair<__first_node, __node_allocator> __p1_;
+ __compressed_pair<size_type, hasher> __p2_;
+ __compressed_pair<float, key_equal> __p3_;
// --- Member data end ---
_LIBCPP_INLINE_VISIBILITY
diff --git a/include/ext/hash_map b/include/ext/hash_map
index 3ac27b2ca..388665313 100644
--- a/include/ext/hash_map
+++ b/include/ext/hash_map
@@ -309,7 +309,7 @@ class __hash_map_node_destructor
{
typedef _Alloc allocator_type;
typedef allocator_traits<allocator_type> __alloc_traits;
- typedef typename __alloc_traits::value_type::value_type value_type;
+ typedef typename __alloc_traits::value_type::__node_value_type value_type;
public:
typedef typename __alloc_traits::pointer pointer;
private:
diff --git a/include/unordered_map b/include/unordered_map
index 85a54a7b6..a05c2b5ef 100644
--- a/include/unordered_map
+++ b/include/unordered_map
@@ -384,6 +384,7 @@ template <class _Key, class _Cp, class _Hash,
class __unordered_map_hasher
: private _Hash
{
+ typedef typename __key_value_types<_Cp>::__map_value_type _PairT;
public:
_LIBCPP_INLINE_VISIBILITY
__unordered_map_hasher()
@@ -414,6 +415,7 @@ class __unordered_map_hasher<_Key, _Cp, _Hash, false>
{
_Hash __hash_;
+ typedef typename __key_value_types<_Cp>::__map_value_type _PairT;
public:
_LIBCPP_INLINE_VISIBILITY
__unordered_map_hasher()
@@ -455,6 +457,7 @@ template <class _Key, class _Cp, class _Pred,
class __unordered_map_equal
: private _Pred
{
+ typedef typename __key_value_types<_Cp>::__map_value_type _PairT;
public:
_LIBCPP_INLINE_VISIBILITY
__unordered_map_equal()
@@ -488,6 +491,7 @@ class __unordered_map_equal<_Key, _Cp, _Pred, false>
{
_Pred __pred_;
+ typedef typename __key_value_types<_Cp>::__map_value_type _PairT;
public:
_LIBCPP_INLINE_VISIBILITY
__unordered_map_equal()
@@ -508,6 +512,9 @@ public:
_LIBCPP_INLINE_VISIBILITY
bool operator()(const _Key& __x, const _Cp& __y) const
{return __pred_(__x, __y.__cc.first);}
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator()(const _Key& __x, const _PairT& __y) const
+ {return __pred_(__x, __y.first);}
void swap(__unordered_map_equal&__y)
_NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
{
@@ -531,12 +538,11 @@ class __hash_map_node_destructor
{
typedef _Alloc allocator_type;
typedef allocator_traits<allocator_type> __alloc_traits;
- typedef typename __alloc_traits::value_type::value_type value_type;
+
public:
- typedef typename __alloc_traits::pointer pointer;
+
+ typedef typename __alloc_traits::pointer pointer;
private:
- typedef typename value_type::value_type::first_type first_type;
- typedef typename value_type::value_type::second_type second_type;
allocator_type& __na_;
@@ -656,15 +662,14 @@ class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator
{
_HashIterator __i_;
- typedef const typename _HashIterator::value_type::value_type::first_type key_type;
- typedef typename _HashIterator::value_type::value_type::second_type mapped_type;
+ typedef __hash_node_types_from_iterator<_HashIterator> _NodeTypes;
+
public:
typedef forward_iterator_tag iterator_category;
- typedef pair<key_type, mapped_type> value_type;
- typedef typename _HashIterator::difference_type difference_type;
+ typedef typename _NodeTypes::__map_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
typedef value_type& reference;
- typedef typename __rebind_pointer<typename _HashIterator::pointer, value_type>::type
- pointer;
+ typedef typename _NodeTypes::__map_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY
__hash_map_iterator() _NOEXCEPT {}
@@ -706,15 +711,14 @@ class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator
{
_HashIterator __i_;
- typedef const typename _HashIterator::value_type::value_type::first_type key_type;
- typedef typename _HashIterator::value_type::value_type::second_type mapped_type;
+ typedef __hash_node_types_from_iterator<_HashIterator> _NodeTypes;
+
public:
typedef forward_iterator_tag iterator_category;
- typedef pair<key_type, mapped_type> value_type;
- typedef typename _HashIterator::difference_type difference_type;
+ typedef typename _NodeTypes::__map_value_type value_type;
+ typedef typename _NodeTypes::difference_type difference_type;
typedef const value_type& reference;
- typedef typename __rebind_pointer<typename _HashIterator::pointer, const value_type>::type
- pointer;
+ typedef typename _NodeTypes::__const_map_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY
__hash_map_const_iterator() _NOEXCEPT {}
@@ -796,8 +800,8 @@ private:
public:
typedef typename __alloc_traits::pointer pointer;
typedef typename __alloc_traits::const_pointer const_pointer;
- typedef typename __alloc_traits::size_type size_type;
- typedef typename __alloc_traits::difference_type difference_type;
+ typedef typename __table::size_type size_type;
+ typedef typename __table::difference_type difference_type;
typedef __hash_map_iterator<typename __table::iterator> iterator;
typedef __hash_map_const_iterator<typename __table::const_iterator> const_iterator;
@@ -1641,11 +1645,14 @@ private:
typedef __hash_map_node_destructor<__node_allocator> _Dp;
typedef unique_ptr<__node, _Dp> __node_holder;
typedef allocator_traits<allocator_type> __alloc_traits;
+ static_assert((is_same<typename __node_traits::size_type,
+ typename __alloc_traits::size_type>::value),
+ "Allocator uses different size_type for different types");
public:
typedef typename __alloc_traits::pointer pointer;
typedef typename __alloc_traits::const_pointer const_pointer;
- typedef typename __alloc_traits::size_type size_type;
- typedef typename __alloc_traits::difference_type difference_type;
+ typedef typename __table::size_type size_type;
+ typedef typename __table::difference_type difference_type;
typedef __hash_map_iterator<typename __table::iterator> iterator;
typedef __hash_map_const_iterator<typename __table::const_iterator> const_iterator;
diff --git a/test/libcxx/containers/unord/key_value_traits.pass.cpp b/test/libcxx/containers/unord/key_value_traits.pass.cpp
new file mode 100644
index 000000000..0df259016
--- /dev/null
+++ b/test/libcxx/containers/unord/key_value_traits.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <__hash_table>
+#include <unordered_map>
+#include <unordered_set>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+void testKeyValueTrait() {
+ {
+ typedef int Tp;
+ typedef std::__key_value_types<Tp> Traits;
+ static_assert((std::is_same<Traits::key_type, int>::value), "");
+ static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+ static_assert(Traits::__is_map == false, "");
+ }
+ {
+ typedef std::pair<int, int> Tp;
+ typedef std::__key_value_types<Tp> Traits;
+ static_assert((std::is_same<Traits::key_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+ static_assert(Traits::__is_map == false, "");
+ }
+ {
+ typedef std::pair<const int, int> Tp;
+ typedef std::__key_value_types<Tp> Traits;
+ static_assert((std::is_same<Traits::key_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
+ static_assert(Traits::__is_map == false, "");
+ }
+ {
+ typedef std::__hash_value_type<int, int> Tp;
+ typedef std::__key_value_types<Tp> Traits;
+ static_assert((std::is_same<Traits::key_type, int>::value), "");
+ static_assert((std::is_same<Traits::mapped_type, int>::value), "");
+ static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
+ static_assert((std::is_same<Traits::__container_value_type,
+ std::pair<const int, int> >::value), "");
+ static_assert((std::is_same<Traits::__map_value_type,
+ std::pair<const int, int> >::value), "");
+ static_assert(Traits::__is_map == true, "");
+ }
+}
+
+int main() {
+ testKeyValueTrait();
+}
diff --git a/test/std/containers/unord/iterator_difference_type.pass.cpp b/test/std/containers/unord/iterator_difference_type.pass.cpp
new file mode 100644
index 000000000..35bcc2794
--- /dev/null
+++ b/test/std/containers/unord/iterator_difference_type.pass.cpp
@@ -0,0 +1,154 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <unordered_map>
+#include <unordered_set>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+
+template <class Map, class ValueTp, class PtrT, class CPtrT>
+void testUnorderedMap() {
+ typedef typename Map::difference_type Diff;
+ {
+ typedef typename Map::iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp&>::value), "");
+ static_assert((std::is_same<typename It::pointer, PtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+ }
+ {
+ typedef typename Map::const_iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+ static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+ }
+ {
+ typedef typename Map::local_iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp&>::value), "");
+ static_assert((std::is_same<typename It::pointer, PtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+ }
+ {
+ typedef typename Map::const_local_iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+ static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+ }
+}
+
+
+template <class Set, class ValueTp, class CPtrT>
+void testUnorderedSet() {
+ static_assert((std::is_same<typename Set::iterator,
+ typename Set::const_iterator>::value), "");
+ static_assert((std::is_same<typename Set::local_iterator,
+ typename Set::const_local_iterator>::value), "");
+ typedef typename Set::difference_type Diff;
+ {
+ typedef typename Set::iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+ static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+
+ }
+ {
+ typedef typename Set::local_iterator It;
+ static_assert((std::is_same<typename It::value_type, ValueTp>::value), "");
+ static_assert((std::is_same<typename It::reference, ValueTp const&>::value), "");
+ static_assert((std::is_same<typename It::pointer, CPtrT>::value), "");
+ static_assert((std::is_same<typename It::difference_type, Diff>::value), "");
+ }
+}
+
+int main() {
+ {
+ typedef std::unordered_map<int, int> Map;
+ typedef std::pair<const int, int> ValueTp;
+ testUnorderedMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+ }
+ {
+ typedef std::pair<const int, int> ValueTp;
+ typedef test_allocator<ValueTp> Alloc;
+ typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, Alloc> Map;
+ testUnorderedMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+ }
+#if TEST_STD_VER >= 11
+ {
+ typedef std::pair<const int, int> ValueTp;
+ typedef min_allocator<ValueTp> Alloc;
+ typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, Alloc> Map;
+ testUnorderedMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
+ }
+#endif
+ {
+ typedef std::unordered_multimap<int, int> Map;
+ typedef std::pair<const int, int> ValueTp;
+ testUnorderedMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+ }
+ {
+ typedef std::pair<const int, int> ValueTp;
+ typedef test_allocator<ValueTp> Alloc;
+ typedef std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, Alloc> Map;
+ testUnorderedMap<Map, ValueTp, ValueTp*, ValueTp const*>();
+ }
+#if TEST_STD_VER >= 11
+ {
+ typedef std::pair<const int, int> ValueTp;
+ typedef min_allocator<ValueTp> Alloc;
+ typedef std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, Alloc> Map;
+ testUnorderedMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
+ }
+#endif
+ {
+ typedef int ValueTp;
+ typedef std::unordered_set<ValueTp> Set;
+ testUnorderedSet<Set, ValueTp, ValueTp const*>();
+ }
+ {
+ typedef int ValueTp;
+ typedef test_allocator<ValueTp> Alloc;
+ typedef std::unordered_set<ValueTp, std::hash<ValueTp>, std::equal_to<ValueTp>, Alloc> Set;
+ testUnorderedSet<Set, ValueTp, ValueTp const*>();
+ }
+#if TEST_STD_VER >= 11
+ {
+ typedef int ValueTp;
+ typedef min_allocator<ValueTp> Alloc;
+ typedef std::unordered_set<ValueTp, std::hash<ValueTp>, std::equal_to<ValueTp>, Alloc> Set;
+ testUnorderedSet<Set, ValueTp, min_pointer<const ValueTp>>();
+ }
+#endif
+ {
+ typedef int ValueTp;
+ typedef std::unordered_multiset<ValueTp> Set;
+ testUnorderedSet<Set, ValueTp, ValueTp const*>();
+ }
+ {
+ typedef int ValueTp;
+ typedef test_allocator<ValueTp> Alloc;
+ typedef std::unordered_multiset<ValueTp, std::hash<ValueTp>, std::equal_to<ValueTp>, Alloc> Set;
+ testUnorderedSet<Set, ValueTp, ValueTp const*>();
+ }
+#if TEST_STD_VER >= 11
+ {
+ typedef int ValueTp;
+ typedef min_allocator<ValueTp> Alloc;
+ typedef std::unordered_multiset<ValueTp, std::hash<ValueTp>, std::equal_to<ValueTp>, Alloc> Set;
+ testUnorderedSet<Set, ValueTp, min_pointer<const ValueTp>>();
+ }
+#endif
+}
diff --git a/test/std/containers/unord/unord.map/incomplete_type.pass.cpp b/test/std/containers/unord/unord.map/incomplete_type.pass.cpp
new file mode 100644
index 000000000..d51b1d8d1
--- /dev/null
+++ b/test/std/containers/unord/unord.map/incomplete_type.pass.cpp
@@ -0,0 +1,37 @@
+
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// Check that std::unordered_map and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <unordered_map>
+
+template <class Tp>
+struct MyHash {
+ MyHash() {}
+ std::size_t operator()(Tp const&) const {return 42;}
+};
+
+struct A {
+ typedef std::unordered_map<A, A, MyHash<A> > Map;
+ Map m;
+ Map::iterator it;
+ Map::const_iterator cit;
+ Map::local_iterator lit;
+ Map::const_local_iterator clit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+
+int main() {
+ A a;
+}
diff --git a/test/std/containers/unord/unord.multimap/incomplete.pass.cpp b/test/std/containers/unord/unord.multimap/incomplete.pass.cpp
new file mode 100644
index 000000000..7822224e7
--- /dev/null
+++ b/test/std/containers/unord/unord.multimap/incomplete.pass.cpp
@@ -0,0 +1,37 @@
+
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// Check that std::unordered_multimap and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <unordered_map>
+
+template <class Tp>
+struct MyHash {
+ MyHash() {}
+ std::size_t operator()(Tp const&) const {return 42;}
+};
+
+struct A {
+ typedef std::unordered_multimap<A, A, MyHash<A> > Map;
+ Map m;
+ Map::iterator it;
+ Map::const_iterator cit;
+ Map::local_iterator lit;
+ Map::const_local_iterator clit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+
+int main() {
+ A a;
+}
diff --git a/test/std/containers/unord/unord.multiset/incomplete.pass.cpp b/test/std/containers/unord/unord.multiset/incomplete.pass.cpp
new file mode 100644
index 000000000..f6d8dc17c
--- /dev/null
+++ b/test/std/containers/unord/unord.multiset/incomplete.pass.cpp
@@ -0,0 +1,38 @@
+
+
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// Check that std::unordered_multiset and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <unordered_set>
+
+template <class Tp>
+struct MyHash {
+ MyHash() {}
+ std::size_t operator()(Tp const&) const {return 42;}
+};
+
+struct A {
+ typedef std::unordered_multiset<A, MyHash<A> > Map;
+ Map m;
+ Map::iterator it;
+ Map::const_iterator cit;
+ Map::local_iterator lit;
+ Map::const_local_iterator clit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+
+int main() {
+ A a;
+}
diff --git a/test/std/containers/unord/unord.set/incomplete.pass.cpp b/test/std/containers/unord/unord.set/incomplete.pass.cpp
new file mode 100644
index 000000000..c970c1de5
--- /dev/null
+++ b/test/std/containers/unord/unord.set/incomplete.pass.cpp
@@ -0,0 +1,38 @@
+
+
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// Check that std::unordered_set and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <unordered_set>
+
+template <class Tp>
+struct MyHash {
+ MyHash() {}
+ std::size_t operator()(Tp const&) const {return 42;}
+};
+
+struct A {
+ typedef std::unordered_set<A, MyHash<A> > Map;
+ Map m;
+ Map::iterator it;
+ Map::const_iterator cit;
+ Map::local_iterator lit;
+ Map::const_local_iterator clit;
+};
+
+inline bool operator==(A const& L, A const& R) { return &L == &R; }
+
+int main() {
+ A a;
+}