[libcxx] r260431 - Recommit r260012 - Cleanup node-type handling in the unordered containers.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 10 12:46:23 PST 2016


Author: ericwf
Date: Wed Feb 10 14:46:23 2016
New Revision: 260431

URL: http://llvm.org/viewvc/llvm-project?rev=260431&view=rev
Log:
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.

Added:
    libcxx/trunk/test/libcxx/containers/unord/key_value_traits.pass.cpp
    libcxx/trunk/test/std/containers/unord/iterator_difference_type.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.map/incomplete_type.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multimap/incomplete.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multiset/incomplete.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.set/incomplete.pass.cpp
Modified:
    libcxx/trunk/include/__config
    libcxx/trunk/include/__hash_table
    libcxx/trunk/include/ext/hash_map
    libcxx/trunk/include/unordered_map

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=260431&r1=260430&r2=260431&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Wed Feb 10 14:46:23 2016
@@ -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

Modified: libcxx/trunk/include/__hash_table
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__hash_table?rev=260431&r1=260430&r2=260431&view=diff
==============================================================================
--- libcxx/trunk/include/__hash_table (original)
+++ libcxx/trunk/include/__hash_table Wed Feb 10 14:46:23 2016
@@ -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
     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

Modified: libcxx/trunk/include/ext/hash_map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ext/hash_map?rev=260431&r1=260430&r2=260431&view=diff
==============================================================================
--- libcxx/trunk/include/ext/hash_map (original)
+++ libcxx/trunk/include/ext/hash_map Wed Feb 10 14:46:23 2016
@@ -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:

Modified: libcxx/trunk/include/unordered_map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_map?rev=260431&r1=260430&r2=260431&view=diff
==============================================================================
--- libcxx/trunk/include/unordered_map (original)
+++ libcxx/trunk/include/unordered_map Wed Feb 10 14:46:23 2016
@@ -384,6 +384,7 @@ template <class _Key, class _Cp, class _
 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 __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 _
 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 __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_i
 {
     _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_c
 {
     _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;

Added: libcxx/trunk/test/libcxx/containers/unord/key_value_traits.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/unord/key_value_traits.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/containers/unord/key_value_traits.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/containers/unord/key_value_traits.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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();
+}

Added: libcxx/trunk/test/std/containers/unord/iterator_difference_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/iterator_difference_type.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/iterator_difference_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/iterator_difference_type.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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
+}

Added: libcxx/trunk/test/std/containers/unord/unord.map/incomplete_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.map/incomplete_type.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.map/incomplete_type.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.map/incomplete_type.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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;
+}

Added: libcxx/trunk/test/std/containers/unord/unord.multimap/incomplete.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multimap/incomplete.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multimap/incomplete.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.multimap/incomplete.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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;
+}

Added: libcxx/trunk/test/std/containers/unord/unord.multiset/incomplete.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multiset/incomplete.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multiset/incomplete.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.multiset/incomplete.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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;
+}

Added: libcxx/trunk/test/std/containers/unord/unord.set/incomplete.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.set/incomplete.pass.cpp?rev=260431&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.set/incomplete.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.set/incomplete.pass.cpp Wed Feb 10 14:46:23 2016
@@ -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;
+}




More information about the cfe-commits mailing list