Cleanup node-type handling in the associative containers.

This patch is very similar to r260431.

This patch is the first in a series of patches that's meant to better
support map. 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 __tree about this
special value_type.

This patch creates a "__tree_node_types" traits class that contains
all of the typedefs needed by the associative containers and their iterators.
These typedefs include ones for each node type and  node pointer type,
as well as special typedefs for "map"'s value type.

Although the associative containers already supported incomplete types, this
patch makes it official by adding tests.

This patch will be followed up shortly with various cleanups within __tree and
fixes for various map bugs and problems.

llvm-svn: 261416
This commit is contained in:
Eric Fiselier 2016-02-20 05:28:30 +00:00
parent 74caaf27d8
commit 089a7cc5de
8 changed files with 489 additions and 78 deletions

View File

@ -29,6 +29,22 @@ template <class _Tp, class _NodePtr, class _DiffType>
template <class _Tp, class _ConstNodePtr, class _DiffType>
class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator;
template <class _Pointer> class __tree_end_node;
template <class _VoidPtr> class __tree_node_base;
template <class _Tp, class _VoidPtr> class __tree_node;
#ifndef _LIBCPP_CXX03_LANG
template <class _Key, class _Value>
union __value_type;
#else
template <class _Key, class _Value>
struct __value_type;
#endif
template <class _Allocator> class __map_node_destructor;
template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
/*
_NodePtr algorithms
@ -494,14 +510,12 @@ __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT
}
}
template <class _Allocator> class __map_node_destructor;
template <class _Allocator>
class __tree_node_destructor
{
typedef _Allocator 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:
@ -531,6 +545,92 @@ public:
template <class> friend class __map_node_destructor;
};
// node traits
template <class _Tp>
struct __tree_key_value_types {
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 __tree_key_value_types<__value_type<_Key, _Tp> > {
typedef _Key key_type;
typedef _Tp mapped_type;
typedef __value_type<_Key, _Tp> __node_value_type;
typedef pair<const _Key, _Tp> __container_value_type;
typedef pair<_Key, _Tp> __nc_value_type;
typedef __container_value_type __map_value_type;
static const bool __is_map = true;
};
template <class _VoidPtr>
struct __tree_node_base_types {
typedef _VoidPtr __void_pointer;
typedef __tree_node_base<__void_pointer> __node_base_type;
typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type
__node_base_pointer;
typedef __tree_end_node<__node_base_pointer> __end_node_type;
typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type
__end_node_pointer;
private:
static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
"_VoidPtr does not point to unqualified void type");
};
template <class _Tp, class _AllocPtr, class _KVTypes = __tree_key_value_types<_Tp>,
bool = _KVTypes::__is_map>
struct __tree_map_pointer_types {};
template <class _Tp, class _AllocPtr, class _KVTypes>
struct __tree_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 __tree_node_types;
template <class _NodePtr, class _Tp, class _VoidPtr>
struct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> >
: public __tree_node_base_types<_VoidPtr>,
__tree_key_value_types<_Tp>,
__tree_map_pointer_types<_Tp, _VoidPtr>
{
typedef __tree_node_base_types<_VoidPtr> __base;
typedef __tree_key_value_types<_Tp> __key_base;
typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base;
public:
typedef typename pointer_traits<_NodePtr>::element_type __node_type;
typedef _NodePtr __node_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 __rebind_pointer<_VoidPtr, __node_type>::type,
_NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
};
template <class _ValueTp, class _VoidPtr>
struct __make_tree_node_types {
typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type
_NodePtr;
typedef __tree_node_types<_NodePtr> type;
};
// node
template <class _Pointer>
@ -546,18 +646,14 @@ public:
template <class _VoidPtr>
class __tree_node_base
: public __tree_end_node
<
typename __rebind_pointer<_VoidPtr, __tree_node_base<_VoidPtr> >::type
>
: public __tree_node_base_types<_VoidPtr>::__end_node_type
{
typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes;
__tree_node_base(const __tree_node_base&);
__tree_node_base& operator=(const __tree_node_base&);
public:
typedef typename __rebind_pointer<_VoidPtr, __tree_node_base>::type pointer;
typedef typename __rebind_pointer<_VoidPtr, const __tree_node_base>::type const_pointer;
typedef __tree_end_node<pointer> base;
typedef typename _NodeBaseTypes::__node_base_pointer pointer;
pointer __right_;
pointer __parent_;
@ -573,10 +669,9 @@ class __tree_node
: public __tree_node_base<_VoidPtr>
{
public:
typedef __tree_node_base<_VoidPtr> base;
typedef _Tp value_type;
typedef _Tp __node_value_type;
value_type __value_;
__node_value_type __value_;
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
template <class ..._Args>
@ -585,29 +680,27 @@ public:
: __value_(_VSTD::forward<_Args>(__args)...) {}
#else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
_LIBCPP_INLINE_VISIBILITY
explicit __tree_node(const value_type& __v)
explicit __tree_node(const __node_value_type& __v)
: __value_(__v) {}
#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
};
template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator;
template <class _Tp, class _NodePtr, class _DiffType>
class _LIBCPP_TYPE_VIS_ONLY __tree_iterator
{
typedef __tree_node_types<_NodePtr> _NodeTypes;
typedef _NodePtr __node_pointer;
typedef typename pointer_traits<__node_pointer>::element_type __node;
typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
typedef pointer_traits<__node_pointer> __pointer_traits;
__node_pointer __ptr_;
typedef pointer_traits<__node_pointer> __pointer_traits;
public:
typedef bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _DiffType 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 __tree_iterator() _NOEXCEPT
#if _LIBCPP_STD_VER > 11
@ -622,7 +715,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
__tree_iterator& operator++() {
__ptr_ = static_cast<__node_pointer>(
__tree_next(static_cast<typename __node::base::pointer>(__ptr_)));
__tree_next(static_cast<__node_base_pointer>(__ptr_)));
return *this;
}
_LIBCPP_INLINE_VISIBILITY
@ -632,7 +725,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
__tree_iterator& operator--() {
__ptr_ = static_cast<__node_pointer>(
__tree_prev(static_cast<typename __node::base::pointer>(__ptr_)));
__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
return *this;
}
_LIBCPP_INLINE_VISIBILITY
@ -658,21 +751,22 @@ private:
template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset;
};
template <class _Tp, class _ConstNodePtr, class _DiffType>
template <class _Tp, class _NodePtr, class _DiffType>
class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator
{
typedef _ConstNodePtr __node_pointer;
typedef typename pointer_traits<__node_pointer>::element_type __node;
typedef __tree_node_types<_NodePtr> _NodeTypes;
typedef typename _NodeTypes::__node_pointer __node_pointer;
typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
typedef pointer_traits<__node_pointer> __pointer_traits;
__node_pointer __ptr_;
typedef pointer_traits<__node_pointer> __pointer_traits;
public:
typedef bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _DiffType difference_type;
typedef const value_type& reference;
typedef typename __rebind_pointer<__node_pointer, const value_type>::type pointer;
typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT
#if _LIBCPP_STD_VER > 11
@ -681,10 +775,7 @@ public:
{}
private:
typedef typename remove_const<__node>::type __non_const_node;
typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type
__non_const_node_pointer;
typedef __tree_iterator<value_type, __non_const_node_pointer, difference_type>
typedef __tree_iterator<value_type, __node_pointer, difference_type>
__non_const_iterator;
public:
_LIBCPP_INLINE_VISIBILITY
@ -697,8 +788,6 @@ public:
_LIBCPP_INLINE_VISIBILITY
__tree_const_iterator& operator++() {
typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type
__node_base_pointer;
__ptr_ = static_cast<__node_pointer>(
__tree_next(static_cast<__node_base_pointer>(__ptr_)));
return *this;
@ -710,8 +799,6 @@ public:
_LIBCPP_INLINE_VISIBILITY
__tree_const_iterator& operator--() {
typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type
__node_base_pointer;
__ptr_ = static_cast<__node_pointer>(
__tree_prev(static_cast<__node_base_pointer>(__ptr_)));
return *this;
@ -747,28 +834,52 @@ public:
typedef _Tp value_type;
typedef _Compare value_compare;
typedef _Allocator allocator_type;
private:
typedef allocator_traits<allocator_type> __alloc_traits;
typedef typename __make_tree_node_types<value_type,
typename __alloc_traits::void_pointer>::type
_NodeTypes;
public:
typedef typename _NodeTypes::__node_value_type __node_value_type;
typedef typename _NodeTypes::__container_value_type __container_value_type;
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 __alloc_traits::void_pointer __void_pointer;
public:
typedef typename _NodeTypes::__void_pointer __void_pointer;
typedef typename _NodeTypes::__node_type __node;
typedef typename _NodeTypes::__node_pointer __node_pointer;
typedef typename _NodeTypes::__node_pointer __node_const_pointer;
typedef typename _NodeTypes::__node_base_type __node_base;
typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
typedef typename _NodeTypes::__node_base_pointer __node_base_const_pointer;
typedef typename _NodeTypes::__end_node_type __end_node_t;
typedef typename _NodeTypes::__end_node_pointer __end_node_ptr;
typedef typename _NodeTypes::__end_node_pointer __end_node_const_ptr;
typedef __tree_node<value_type, __void_pointer> __node;
typedef __tree_node_base<__void_pointer> __node_base;
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 typename __node_base::pointer __node_base_pointer;
typedef typename __node_base::pointer __node_base_const_pointer;
private:
typedef typename __node_base::base __end_node_t;
typedef typename __rebind_pointer<__node_pointer, __end_node_t>::type
__end_node_ptr;
typedef __end_node_ptr __end_node_const_ptr;
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, __node_base>::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:
__node_pointer __begin_node_;
__compressed_pair<__end_node_t, __node_allocator> __pair1_;
__compressed_pair<size_type, value_compare> __pair3_;

View File

@ -564,13 +564,11 @@ class __map_node_destructor
{
typedef _Allocator 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:
typedef typename value_type::value_type::first_type first_type;
typedef typename value_type::value_type::second_type second_type;
private:
allocator_type& __na_;
__map_node_destructor& operator=(const __map_node_destructor&);
@ -615,7 +613,7 @@ template <class _Key, class _Tp, class _Compare, class _Allocator>
class multimap;
template <class _TreeIterator> class __map_const_iterator;
#if __cplusplus >= 201103L
#ifndef _LIBCPP_CXX03_LANG
template <class _Key, class _Tp>
union __value_type
@ -697,19 +695,17 @@ struct __extract_key_value_types<__value_type<_Key, _Tp> >
template <class _TreeIterator>
class _LIBCPP_TYPE_VIS_ONLY __map_iterator
{
typedef typename _TreeIterator::_NodeTypes _NodeTypes;
typedef typename _TreeIterator::__pointer_traits __pointer_traits;
_TreeIterator __i_;
typedef typename _TreeIterator::__pointer_traits __pointer_traits;
typedef typename _TreeIterator::value_type __value_type;
typedef typename __extract_key_value_types<__value_type>::__key_type __key_type;
typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type;
public:
typedef bidirectional_iterator_tag iterator_category;
typedef pair<__key_type, __mapped_type> value_type;
typedef typename _NodeTypes::__map_value_type value_type;
typedef typename _TreeIterator::difference_type difference_type;
typedef value_type& reference;
typedef typename __rebind_pointer<typename __pointer_traits::pointer, value_type>::type
pointer;
typedef typename _NodeTypes::__map_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY
__map_iterator() _NOEXCEPT {}
@ -758,19 +754,17 @@ public:
template <class _TreeIterator>
class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator
{
typedef typename _TreeIterator::_NodeTypes _NodeTypes;
typedef typename _TreeIterator::__pointer_traits __pointer_traits;
_TreeIterator __i_;
typedef typename _TreeIterator::__pointer_traits __pointer_traits;
typedef typename _TreeIterator::value_type __value_type;
typedef typename __extract_key_value_types<__value_type>::__key_type __key_type;
typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type;
public:
typedef bidirectional_iterator_tag iterator_category;
typedef pair<__key_type, __mapped_type> value_type;
typedef typename _NodeTypes::__map_value_type value_type;
typedef typename _TreeIterator::difference_type difference_type;
typedef const value_type& reference;
typedef typename __rebind_pointer<typename __pointer_traits::pointer, const value_type>::type
pointer;
typedef typename _NodeTypes::__const_map_value_type_pointer pointer;
_LIBCPP_INLINE_VISIBILITY
__map_const_iterator() _NOEXCEPT {}

View File

@ -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 <__tree>
#include <map>
#include <set>
#include <type_traits>
#include "test_macros.h"
#include "min_allocator.h"
void testKeyValueTrait() {
{
typedef int Tp;
typedef std::__tree_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::__tree_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::__tree_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::__value_type<int, int> Tp;
typedef std::__tree_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();
}

View File

@ -0,0 +1,131 @@
//===----------------------------------------------------------------------===//
//
// 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 <map>
#include <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 testMap() {
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), "");
}
}
template <class Set, class ValueTp, class CPtrT>
void testSet() {
static_assert((std::is_same<typename Set::iterator,
typename Set::const_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), "");
}
}
int main() {
{
typedef std::map<int, int> Map;
typedef std::pair<const int, int> ValueTp;
testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
}
{
typedef std::pair<const int, int> ValueTp;
typedef test_allocator<ValueTp> Alloc;
typedef std::map<int, int, std::less<int>, Alloc> Map;
testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
}
#if TEST_STD_VER >= 11
{
typedef std::pair<const int, int> ValueTp;
typedef min_allocator<ValueTp> Alloc;
typedef std::map<int, int, std::less<int>, Alloc> Map;
testMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
}
#endif
{
typedef std::multimap<int, int> Map;
typedef std::pair<const int, int> ValueTp;
testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
}
{
typedef std::pair<const int, int> ValueTp;
typedef test_allocator<ValueTp> Alloc;
typedef std::multimap<int, int, std::less<int>, Alloc> Map;
testMap<Map, ValueTp, ValueTp*, ValueTp const*>();
}
#if TEST_STD_VER >= 11
{
typedef std::pair<const int, int> ValueTp;
typedef min_allocator<ValueTp> Alloc;
typedef std::multimap<int, int, std::less<int>, Alloc> Map;
testMap<Map, ValueTp, min_pointer<ValueTp>, min_pointer<const ValueTp>>();
}
#endif
{
typedef int ValueTp;
typedef std::set<ValueTp> Set;
testSet<Set, ValueTp, ValueTp const*>();
}
{
typedef int ValueTp;
typedef test_allocator<ValueTp> Alloc;
typedef std::set<ValueTp, std::less<ValueTp>, Alloc> Set;
testSet<Set, ValueTp, ValueTp const*>();
}
#if TEST_STD_VER >= 11
{
typedef int ValueTp;
typedef min_allocator<ValueTp> Alloc;
typedef std::set<ValueTp, std::less<ValueTp>, Alloc> Set;
testSet<Set, ValueTp, min_pointer<const ValueTp>>();
}
#endif
{
typedef int ValueTp;
typedef std::multiset<ValueTp> Set;
testSet<Set, ValueTp, ValueTp const*>();
}
{
typedef int ValueTp;
typedef test_allocator<ValueTp> Alloc;
typedef std::multiset<ValueTp, std::less<ValueTp>, Alloc> Set;
testSet<Set, ValueTp, ValueTp const*>();
}
#if TEST_STD_VER >= 11
{
typedef int ValueTp;
typedef min_allocator<ValueTp> Alloc;
typedef std::multiset<ValueTp, std::less<ValueTp>, Alloc> Set;
testSet<Set, ValueTp, min_pointer<const ValueTp>>();
}
#endif
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <map>
// Check that std::map and it's iterators can be instantiated with an incomplete
// type.
#include <map>
struct A {
typedef std::map<A, A> Map;
int data;
Map m;
Map::iterator it;
Map::const_iterator cit;
};
inline bool operator==(A const& L, A const& R) { return &L == &R; }
inline bool operator<(A const& L, A const& R) { return L.data < R.data; }
int main() {
A a;
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <map>
// Check that std::multimap and it's iterators can be instantiated with an incomplete
// type.
#include <map>
struct A {
typedef std::multimap<A, A> Map;
int data;
Map m;
Map::iterator it;
Map::const_iterator cit;
};
inline bool operator==(A const& L, A const& R) { return &L == &R; }
inline bool operator<(A const& L, A const& R) { return L.data < R.data; }
int main() {
A a;
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <set>
// Check that std::multiset and it's iterators can be instantiated with an incomplete
// type.
#include <set>
struct A {
typedef std::multiset<A> Set;
int data;
Set m;
Set::iterator it;
Set::const_iterator cit;
};
inline bool operator==(A const& L, A const& R) { return &L == &R; }
inline bool operator<(A const& L, A const& R) { return L.data < R.data; }
int main() {
A a;
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <set>
// Check that std::set and it's iterators can be instantiated with an incomplete
// type.
#include <set>
struct A {
typedef std::set<A> Set;
int data;
Set m;
Set::iterator it;
Set::const_iterator cit;
};
inline bool operator==(A const& L, A const& R) { return &L == &R; }
inline bool operator<(A const& L, A const& R) { return L.data < R.data; }
int main() {
A a;
}