From 75d0dcfde74dcdb2aacfbfa0a52d8bf72416336b Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 10 Feb 2016 20:46:23 +0000 Subject: [PATCH] Recommit r260012 - Cleanup node-type handling in the unordered containers. This time I kept 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. 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. llvm-svn: 260431 --- libcxx/include/__config | 1 + libcxx/include/__hash_table | 218 ++++++++++++++++----- libcxx/include/ext/hash_map | 2 +- libcxx/include/unordered_map | 47 +++-- .../containers/unord/key_value_traits.pass.cpp | 59 ++++++ .../unord/iterator_difference_type.pass.cpp | 154 +++++++++++++++ .../unord/unord.map/incomplete_type.pass.cpp | 37 ++++ .../unord/unord.multimap/incomplete.pass.cpp | 37 ++++ .../unord/unord.multiset/incomplete.pass.cpp | 38 ++++ .../containers/unord/unord.set/incomplete.pass.cpp | 38 ++++ 10 files changed, 559 insertions(+), 72 deletions(-) create mode 100644 libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp create mode 100644 libcxx/test/std/containers/unord/iterator_difference_type.pass.cpp create mode 100644 libcxx/test/std/containers/unord/unord.map/incomplete_type.pass.cpp create mode 100644 libcxx/test/std/containers/unord/unord.multimap/incomplete.pass.cpp create mode 100644 libcxx/test/std/containers/unord/unord.multiset/incomplete.pass.cpp create mode 100644 libcxx/test/std/containers/unord/unord.set/incomplete.pass.cpp diff --git a/libcxx/include/__config b/libcxx/include/__config index 83e6e2a..5921662 100644 --- a/libcxx/include/__config +++ b/libcxx/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/libcxx/include/__hash_table b/libcxx/include/__hash_table index c48e383..5f21de4 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -17,6 +17,7 @@ #include #include #include +#include #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 __hash_table; + +template class _LIBCPP_TYPE_VIS_ONLY __hash_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; +#if __cplusplus >= 201103L +template +union __hash_value_type; +#else +template +struct __hash_value_type; +#endif + +template +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 +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 __container_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; +}; + +template , + bool = _KVTypes::__is_map> +struct __map_pointer_types {}; + +template +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 ::element_type> +struct __hash_node_types; + +template +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::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); + static_assert((is_same::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + + + +template +struct __hash_node_types_from_iterator; +template +struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; + + +template +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 _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 friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; }; -template +template 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::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 friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; }; -template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; - template 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 _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 __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 __alloc_traits; + typedef typename + __make_hash_node_types::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 __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 __p2_; - __compressed_pair __p3_; + __bucket_list __bucket_list_; + __compressed_pair<__first_node, __node_allocator> __p1_; + __compressed_pair __p2_; + __compressed_pair __p3_; // --- Member data end --- _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map index 3ac27b2..3886653 100644 --- a/libcxx/include/ext/hash_map +++ b/libcxx/include/ext/hash_map @@ -309,7 +309,7 @@ class __hash_map_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __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/libcxx/include/unordered_map b/libcxx/include/unordered_map index 85a54a7..a05c2b5 100644 --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -384,6 +384,7 @@ template ::__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 ::__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 __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 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::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 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::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 iterator; typedef __hash_map_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 __alloc_traits; + static_assert((is_same::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 iterator; typedef __hash_map_const_iterator const_iterator; diff --git a/libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp b/libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp new file mode 100644 index 0000000..0df2590 --- /dev/null +++ b/libcxx/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 +#include +#include + +#include "test_macros.h" +#include "min_allocator.h" + +void testKeyValueTrait() { + { + typedef int Tp; + typedef std::__key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::pair Tp; + typedef std::__key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::pair Tp; + typedef std::__key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert(Traits::__is_map == false, ""); + } + { + typedef std::__hash_value_type Tp; + typedef std::__key_value_types Traits; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same >::value), ""); + static_assert((std::is_same >::value), ""); + static_assert(Traits::__is_map == true, ""); + } +} + +int main() { + testKeyValueTrait(); +} diff --git a/libcxx/test/std/containers/unord/iterator_difference_type.pass.cpp b/libcxx/test/std/containers/unord/iterator_difference_type.pass.cpp new file mode 100644 index 0000000..35bcc27 --- /dev/null +++ b/libcxx/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 +#include +#include + +#include "test_macros.h" +#include "min_allocator.h" +#include "test_allocator.h" + + +template +void testUnorderedMap() { + typedef typename Map::difference_type Diff; + { + typedef typename Map::iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } + { + typedef typename Map::const_iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } + { + typedef typename Map::local_iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } + { + typedef typename Map::const_local_iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } +} + + +template +void testUnorderedSet() { + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + typedef typename Set::difference_type Diff; + { + typedef typename Set::iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + + } + { + typedef typename Set::local_iterator It; + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + } +} + +int main() { + { + typedef std::unordered_map Map; + typedef std::pair ValueTp; + testUnorderedMap(); + } + { + typedef std::pair ValueTp; + typedef test_allocator Alloc; + typedef std::unordered_map, std::equal_to, Alloc> Map; + testUnorderedMap(); + } +#if TEST_STD_VER >= 11 + { + typedef std::pair ValueTp; + typedef min_allocator Alloc; + typedef std::unordered_map, std::equal_to, Alloc> Map; + testUnorderedMap, min_pointer>(); + } +#endif + { + typedef std::unordered_multimap Map; + typedef std::pair ValueTp; + testUnorderedMap(); + } + { + typedef std::pair ValueTp; + typedef test_allocator Alloc; + typedef std::unordered_multimap, std::equal_to, Alloc> Map; + testUnorderedMap(); + } +#if TEST_STD_VER >= 11 + { + typedef std::pair ValueTp; + typedef min_allocator Alloc; + typedef std::unordered_multimap, std::equal_to, Alloc> Map; + testUnorderedMap, min_pointer>(); + } +#endif + { + typedef int ValueTp; + typedef std::unordered_set Set; + testUnorderedSet(); + } + { + typedef int ValueTp; + typedef test_allocator Alloc; + typedef std::unordered_set, std::equal_to, Alloc> Set; + testUnorderedSet(); + } +#if TEST_STD_VER >= 11 + { + typedef int ValueTp; + typedef min_allocator Alloc; + typedef std::unordered_set, std::equal_to, Alloc> Set; + testUnorderedSet>(); + } +#endif + { + typedef int ValueTp; + typedef std::unordered_multiset Set; + testUnorderedSet(); + } + { + typedef int ValueTp; + typedef test_allocator Alloc; + typedef std::unordered_multiset, std::equal_to, Alloc> Set; + testUnorderedSet(); + } +#if TEST_STD_VER >= 11 + { + typedef int ValueTp; + typedef min_allocator Alloc; + typedef std::unordered_multiset, std::equal_to, Alloc> Set; + testUnorderedSet>(); + } +#endif +} diff --git a/libcxx/test/std/containers/unord/unord.map/incomplete_type.pass.cpp b/libcxx/test/std/containers/unord/unord.map/incomplete_type.pass.cpp new file mode 100644 index 0000000..d51b1d8 --- /dev/null +++ b/libcxx/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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::unordered_map and it's iterators can be instantiated with an incomplete +// type. + +#include + +template +struct MyHash { + MyHash() {} + std::size_t operator()(Tp const&) const {return 42;} +}; + +struct A { + typedef std::unordered_map > 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/libcxx/test/std/containers/unord/unord.multimap/incomplete.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/incomplete.pass.cpp new file mode 100644 index 0000000..7822224 --- /dev/null +++ b/libcxx/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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::unordered_multimap and it's iterators can be instantiated with an incomplete +// type. + +#include + +template +struct MyHash { + MyHash() {} + std::size_t operator()(Tp const&) const {return 42;} +}; + +struct A { + typedef std::unordered_multimap > 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/libcxx/test/std/containers/unord/unord.multiset/incomplete.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/incomplete.pass.cpp new file mode 100644 index 0000000..f6d8dc1 --- /dev/null +++ b/libcxx/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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::unordered_multiset and it's iterators can be instantiated with an incomplete +// type. + +#include + +template +struct MyHash { + MyHash() {} + std::size_t operator()(Tp const&) const {return 42;} +}; + +struct A { + typedef std::unordered_multiset > 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/libcxx/test/std/containers/unord/unord.set/incomplete.pass.cpp b/libcxx/test/std/containers/unord/unord.set/incomplete.pass.cpp new file mode 100644 index 0000000..c970c1d --- /dev/null +++ b/libcxx/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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that std::unordered_set and it's iterators can be instantiated with an incomplete +// type. + +#include + +template +struct MyHash { + MyHash() {} + std::size_t operator()(Tp const&) const {return 42;} +}; + +struct A { + typedef std::unordered_set > 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; +} -- 2.7.4