Index: include/__debug =================================================================== --- include/__debug +++ include/__debug @@ -25,6 +25,7 @@ # include # include # include +# include #endif #if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_ASSERT) @@ -37,6 +38,9 @@ #define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(x, m) #endif #define _LIBCPP_DEBUG_MODE(...) __VA_ARGS__ +#define _LIBCPP_DEBUG_PARAM(...) , __VA_ARGS__ +#define _LIBCPP_DEBUG_ITERATOR +#define _LIBCPP_DEBUG_FORCE_INLINE #endif #ifndef _LIBCPP_ASSERT @@ -48,6 +52,12 @@ #ifndef _LIBCPP_DEBUG_MODE #define _LIBCPP_DEBUG_MODE(...) ((void)0) #endif +#ifndef _LIBCPP_DEBUG_PARAM +#define _LIBCPP_DEBUG_PARAM(...) +#endif +#ifndef _LIBCPP_DEBUG_FORCE_INLINE +#define _LIBCPP_DEBUG_FORCE_INLINE _LIBCPP_ALWAYS_INLINE +#endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -83,9 +93,10 @@ _LIBCPP_FUNC_VIS bool __libcpp_set_debug_function(__libcpp_debug_function_type __func); -#if _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY) - struct _LIBCPP_TYPE_VIS __c_node; +struct _LIBCPP_TYPE_VIS __i_node; + +#if _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY) struct _LIBCPP_TYPE_VIS __i_node { @@ -93,15 +104,9 @@ __i_node* __next_; __c_node* __c_; -#ifndef _LIBCPP_CXX03_LANG __i_node(const __i_node&) = delete; __i_node& operator=(const __i_node&) = delete; -#else -private: - __i_node(const __i_node&); - __i_node& operator=(const __i_node&); -public: -#endif + _LIBCPP_INLINE_VISIBILITY __i_node(void* __i, __i_node* __next, __c_node* __c) : __i_(__i), __next_(__next), __c_(__c) {} @@ -116,15 +121,9 @@ __i_node** end_; __i_node** cap_; -#ifndef _LIBCPP_CXX03_LANG __c_node(const __c_node&) = delete; __c_node& operator=(const __c_node&) = delete; -#else -private: - __c_node(const __c_node&); - __c_node& operator=(const __c_node&); -public: -#endif + _LIBCPP_INLINE_VISIBILITY __c_node(void* __c, __c_node* __next) : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} @@ -203,15 +202,9 @@ __libcpp_db(); public: -#ifndef _LIBCPP_CXX03_LANG __libcpp_db(const __libcpp_db&) = delete; __libcpp_db& operator=(const __libcpp_db&) = delete; -#else -private: - __libcpp_db(const __libcpp_db&); - __libcpp_db& operator=(const __libcpp_db&); -public: -#endif + ~__libcpp_db(); class __db_c_iterator; @@ -229,6 +222,12 @@ return ::new(__mem) _C_node<_Cont>(__c, __next); } + template + _LIBCPP_INLINE_VISIBILITY + void __insert_c_helper(void *__c) { + return __insert_c(__c, &__create_C_node<_Cont>); + } + template _LIBCPP_INLINE_VISIBILITY void __insert_c(_Cont* __c) @@ -273,6 +272,158 @@ #endif // _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY) + +template +struct __container_debug_base { +protected: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + __container_debug_base() _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + _VSTD::__get_db()->__insert_c_helper<_Cont>(this); + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + ~__container_debug_base() +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + _VSTD::__get_db()->__erase_c(this); + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + bool __is_valid_iterator(void* __p) _NOEXCEPT + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + return std::__get_const_db()->__find_c_from_i(__p) == this; +#else + ((void)__p); + return true; +#endif + } + + + template + _LIBCPP_INLINE_VISIBILITY + void __remove_iterators_at_position(_Iter __it, _CallBack __convert) _NOEXCEPT { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __p = __c->end_; __p != __c->beg_; ) + { + --__p; + if (__convert((*__p)->__i_) == __it) + { + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + + } + } + __get_db()->unlock(); +#else + ((void)__it); + ((void)__convert); +#endif + } + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + void __remove_iterators_past(_Iter __new_last, _CallBack __convert) _NOEXCEPT { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __p = __c->end_; __p != __c->beg_; ) + { + --__p; + if (__convert((*__p)->__i_) > __new_last) + { + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + } + } + __get_db()->unlock(); +#else + ((void)__new_last); + ((void)__convert); +#endif + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + void __swap_container(void* __other) _NOEXCEPT { + _LIBCPP_DEBUG_MODE(_VSTD::__get_db()->swap(this, __other)); + ((void)__other); + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + void __invalidate_all_iterators() _NOEXCEPT + { + _LIBCPP_DEBUG_MODE(_VSTD::__get_db()->__invalidate_all(this)); + } +}; + +struct __iterator_debug_base { +protected: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + __iterator_debug_base() _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + _VSTD::__get_db()->__insert_i(this); + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + explicit __iterator_debug_base(const void *__c) _NOEXCEPT + { + _LIBCPP_DEBUG_MODE(_VSTD::__get_db()->__insert_ic(this, __c)); + ((void)__c); + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + __iterator_debug_base(__iterator_debug_base const& __other) _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + _VSTD::__get_db()->__iterator_copy(this, &__other); + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + __iterator_debug_base& operator=(__iterator_debug_base const& __other) _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + if (this != &__other) { + _VSTD::__get_db()->__iterator_copy(this, &__other); + }; + return *this; + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE + ~__iterator_debug_base() +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + _VSTD::__get_db()->__erase_i(this); + } +#else + = default; +#endif + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEBUG_FORCE_INLINE + void __check_dereferenceable() const _NOEXCEPT { + _LIBCPP_DEBUG_ASSERT(std::__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable container iterator"); + } +}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_DEBUG_H Index: include/__hash_table =================================================================== --- include/__hash_table +++ include/__hash_table @@ -279,8 +279,9 @@ }; template -class _LIBCPP_TEMPLATE_VIS __hash_iterator +class _LIBCPP_TEMPLATE_VIS __hash_iterator : private __iterator_debug_base { + typedef __iterator_debug_base _DebugBase; typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -295,53 +296,23 @@ typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) { - _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this)); } -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY - __hash_iterator(const __hash_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, &__i); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_iterator& operator=(const __hash_iterator& __i) - { - if (this != &__i) - { - __get_db()->__iterator_copy(this, &__i); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); + _DebugBase::__check_dereferenceable(); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); + _DebugBase::__check_dereferenceable(); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment non-incrementable unordered container iterator"); + _DebugBase::__check_dereferenceable(); __node_ = __node_->__next_; return *this; } @@ -364,19 +335,14 @@ {return !(__x == __y);} private: -#if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY - __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT - : __node_(__node) - { - __get_db()->__insert_ic(this, __c); - } -#else - _LIBCPP_INLINE_VISIBILITY - __hash_iterator(__next_pointer __node) _NOEXCEPT - : __node_(__node) - {} + __hash_iterator(__next_pointer __node _LIBCPP_DEBUG_PARAM(const void* __c)) _NOEXCEPT + : +#if _LIBCPP_DEBUG_LEVEL >= 2 + _DebugBase(__c), #endif + __node_(__node) + {} template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; @@ -385,8 +351,11 @@ }; template -class _LIBCPP_TEMPLATE_VIS __hash_const_iterator +class _LIBCPP_TEMPLATE_VIS __hash_const_iterator : private __iterator_debug_base { + typedef __iterator_debug_base _DebugBase; + + static_assert(!is_const::element_type>::value, ""); typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; @@ -405,59 +374,28 @@ _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) { - _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this)); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT - : __node_(__x.__node_) + : _DebugBase(__x), __node_(__x.__node_) { - _LIBCPP_DEBUG_MODE(__get_db()->__iterator_copy(this, &__x)); } -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator(const __hash_const_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, &__i); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator& operator=(const __hash_const_iterator& __i) - { - if (this != &__i) - { - __get_db()->__iterator_copy(this, &__i); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + _DebugBase::__check_dereferenceable(); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + _DebugBase::__check_dereferenceable(); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment non-incrementable unordered container const_iterator"); + _DebugBase::__check_dereferenceable(); __node_ = __node_->__next_; return *this; } @@ -480,19 +418,16 @@ {return !(__x == __y);} private: -#if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT - : __node_(__node) + __hash_const_iterator(__next_pointer __node _LIBCPP_DEBUG_PARAM(const void* __c)) _NOEXCEPT + : +#if _LIBCPP_DEBUG_LEVEL >= 2 + _DebugBase(__c), +#endif + __node_(__node) { - __get_db()->__insert_ic(this, __c); } -#else - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator(__next_pointer __node) _NOEXCEPT - : __node_(__node) - {} -#endif + template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; template friend class _LIBCPP_TEMPLATE_VIS unordered_map; @@ -500,8 +435,10 @@ }; template -class _LIBCPP_TEMPLATE_VIS __hash_local_iterator +class _LIBCPP_TEMPLATE_VIS __hash_local_iterator : private __iterator_debug_base { + typedef __iterator_debug_base _DebugBase; + typedef __hash_node_types<_NodePtr> _NodeTypes; typedef _NodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -518,57 +455,23 @@ typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) { - _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this)); } -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator(const __hash_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, &__i); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_local_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator& operator=(const __hash_local_iterator& __i) - { - if (this != &__i) - { - __get_db()->__iterator_copy(this, &__i); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + _DebugBase::__check_dereferenceable(); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + _DebugBase::__check_dereferenceable(); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment non-incrementable unordered container local_iterator"); + _DebugBase::__check_dereferenceable(); __node_ = __node_->__next_; if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -593,38 +496,30 @@ {return !(__x == __y);} private: -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT - : __node_(__node), - __bucket_(__bucket), - __bucket_count_(__bucket_count) - { - __get_db()->__insert_ic(this, __c); - if (__node_ != nullptr) - __node_ = __node_->__next_; - } -#else + _LIBCPP_INLINE_VISIBILITY __hash_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count) _NOEXCEPT - : __node_(__node), + size_t __bucket_count _LIBCPP_DEBUG_PARAM(const void* __c)) _NOEXCEPT + : +#if _LIBCPP_DEBUG_LEVEL >= 2 + _DebugBase(__c), +#endif + __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { if (__node_ != nullptr) __node_ = __node_->__next_; } -#endif template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; }; template -class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator +class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator : private __iterator_debug_base { + typedef __iterator_debug_base _DebugBase; typedef __hash_node_types<_ConstNodePtr> _NodeTypes; typedef _ConstNodePtr __node_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; @@ -650,66 +545,32 @@ _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) { - _LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this)); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT - : __node_(__x.__node_), + : _DebugBase(__x), + __node_(__x.__node_), __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) { - _LIBCPP_DEBUG_MODE(__get_db()->__iterator_copy(this, &__x)); - } - -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator(const __hash_const_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, &__i); } - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_local_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) - { - if (this != &__i) - { - __get_db()->__iterator_copy(this, &__i); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + _DebugBase::__check_dereferenceable(); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + _DebugBase::__check_dereferenceable(); return pointer_traits::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment non-incrementable unordered container const_local_iterator"); + _DebugBase::__check_dereferenceable(); __node_ = __node_->__next_; if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -734,30 +595,20 @@ {return !(__x == __y);} private: -#if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT - : __node_(__node), - __bucket_(__bucket), - __bucket_count_(__bucket_count) - { - __get_db()->__insert_ic(this, __c); - if (__node_ != nullptr) - __node_ = __node_->__next_; - } -#else - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count) _NOEXCEPT - : __node_(__node), + size_t __bucket_count _LIBCPP_DEBUG_PARAM(const void* __c)) _NOEXCEPT + : +#if _LIBCPP_DEBUG_LEVEL >= 2 + _DebugBase(__c), +#endif + __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { if (__node_ != nullptr) __node_ = __node_->__next_; } -#endif template friend class __hash_table; template friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; }; @@ -889,7 +740,7 @@ int __diagnose_unordered_container_requirements(void*); template -class __hash_table +class __hash_table : protected __container_debug_base<__hash_table<_Tp, _Hash, _Equal, _Alloc> > { public: typedef _Tp value_type; @@ -898,6 +749,8 @@ typedef _Alloc allocator_type; private: + typedef __container_debug_base<__hash_table<_Tp, _Hash, _Equal, _Alloc> > _DebugBase; + typedef allocator_traits __alloc_traits; typedef typename __make_hash_node_types::type @@ -930,6 +783,19 @@ typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; typedef typename _NodeTypes::__next_pointer __next_pointer; + using _DebugBase::__is_valid_iterator; + + template + _LIBCPP_INLINE_VISIBILITY + static __next_pointer __iter_to_node_ptr(void* __p) _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + return static_cast<_Iter*>(__p)->__node_; + } +#else + = delete; +#endif + private: // check for sane allocator pointer rebinding semantics. Rebinding the // allocator for a new pointer type should be exactly the same as rebinding @@ -1293,11 +1159,7 @@ { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()"); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); -#else - return local_iterator(__bucket_list_[__n], __n, bucket_count()); -#endif + return local_iterator(__bucket_list_[__n], __n, bucket_count() _LIBCPP_DEBUG_PARAM(this)); } _LIBCPP_INLINE_VISIBILITY @@ -1306,11 +1168,7 @@ { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()"); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return local_iterator(nullptr, __n, bucket_count(), this); -#else - return local_iterator(nullptr, __n, bucket_count()); -#endif + return local_iterator(nullptr, __n, bucket_count() _LIBCPP_DEBUG_PARAM(this)); } _LIBCPP_INLINE_VISIBILITY @@ -1319,11 +1177,7 @@ { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()"); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); -#else - return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); -#endif + return const_local_iterator(__bucket_list_[__n], __n, bucket_count() _LIBCPP_DEBUG_PARAM(this)); } _LIBCPP_INLINE_VISIBILITY @@ -1332,11 +1186,7 @@ { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()"); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return const_local_iterator(nullptr, __n, bucket_count(), this); -#else - return const_local_iterator(nullptr, __n, bucket_count()); -#endif + return const_local_iterator(nullptr, __n, bucket_count() _LIBCPP_DEBUG_PARAM(this)); } #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -1497,6 +1347,7 @@ __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } + _DebugBase::__swap_container(std::addressof(__u)); } template @@ -1521,6 +1372,7 @@ size() = __u.size(); __u.size() = 0; } + _DebugBase::__swap_container(std::addressof(__u)); } } @@ -1537,9 +1389,6 @@ #endif __deallocate_node(__p1_.first().__next_); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__erase_c(this); -#endif } template @@ -1572,6 +1421,7 @@ return *this; } + template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) @@ -1581,21 +1431,7 @@ while (__np != nullptr) { __next_pointer __next = __np->__next_; -#if _LIBCPP_DEBUG_LEVEL >= 2 - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast((*__p)->__i_); - if (__i->__node_ == __np) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif + _LIBCPP_DEBUG_MODE(_DebugBase::__remove_iterators_at_position(__np, &__iter_to_node_ptr)); __node_pointer __real_np = __np->__upcast(); __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_)); __node_traits::deallocate(__na, __real_np, 1); @@ -1644,9 +1480,7 @@ __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->swap(this, &__u); -#endif + _DebugBase::__swap_container(std::addressof(__u)); } template @@ -1798,11 +1632,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__p1_.first().__next_, this); -#else - return iterator(__p1_.first().__next_); -#endif + return iterator(__p1_.first().__next_ _LIBCPP_DEBUG_PARAM(this)); } template @@ -1810,11 +1640,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(nullptr, this); -#else - return iterator(nullptr); -#endif + return iterator(nullptr _LIBCPP_DEBUG_PARAM(this)); } template @@ -1822,11 +1648,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL >= 2 - return const_iterator(__p1_.first().__next_, this); -#else - return const_iterator(__p1_.first().__next_); -#endif + return const_iterator(__p1_.first().__next_ _LIBCPP_DEBUG_PARAM(this)); } template @@ -1834,11 +1656,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT { -#if _LIBCPP_DEBUG_LEVEL >= 2 - return const_iterator(nullptr, this); -#else - return const_iterator(nullptr); -#endif + return const_iterator(nullptr _LIBCPP_DEBUG_PARAM(this)); } template @@ -1943,11 +1761,7 @@ __existing_node = __nd->__ptr(); __inserted = true; } -#if _LIBCPP_DEBUG_LEVEL >= 2 - return pair(iterator(__existing_node, this), __inserted); -#else - return pair(iterator(__existing_node), __inserted); -#endif + return pair(iterator(__existing_node _LIBCPP_DEBUG_PARAM(this)), __inserted); } // Prepare the container for an insertion of the value __cp_val with the hash @@ -2041,11 +1855,7 @@ __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_); __node_insert_multi_perform(__cp, __pn); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__cp->__ptr(), this); -#else - return iterator(__cp->__ptr()); -#endif + return iterator(__cp->__ptr() _LIBCPP_DEBUG_PARAM(this)); } template @@ -2053,11 +1863,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( const_iterator __p, __node_pointer __cp) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__is_valid_iterator(&__p), "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered container"); -#endif if (__p != end() && key_eq()(*__p, __cp->__value_)) { __next_pointer __np = __p.__node_; @@ -2076,11 +1884,7 @@ __cp->__next_ = __np; __pp->__next_ = static_cast<__next_pointer>(__cp); ++size(); -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(static_cast<__next_pointer>(__cp), this); -#else - return iterator(static_cast<__next_pointer>(__cp)); -#endif + return iterator(static_cast<__next_pointer>(__cp) _LIBCPP_DEBUG_PARAM(this)); } return __node_insert_multi(__cp); } @@ -2157,11 +1961,7 @@ __inserted = true; } __done: -#if _LIBCPP_DEBUG_LEVEL >= 2 - return pair(iterator(__nd, this), __inserted); -#else - return pair(iterator(__nd), __inserted); -#endif + return pair(iterator(__nd _LIBCPP_DEBUG_PARAM(this)), __inserted); } #ifndef _LIBCPP_CXX03_LANG @@ -2195,11 +1995,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( const_iterator __p, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_ASSERT(__is_valid_iterator(&__p), "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered container"); -#endif + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); @@ -2223,11 +2022,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, const __container_value_type& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__is_valid_iterator(&__p), "unordered container::insert(const_iterator, lvalue) called with an iterator not" " referring to this unordered container"); -#endif __node_holder __h = __construct_node(__x); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); @@ -2397,9 +2194,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__invalidate_all(this); -#endif // _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); @@ -2468,11 +2263,7 @@ { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__nd, this); -#else - return iterator(__nd); -#endif + return iterator(__nd _LIBCPP_DEBUG_PARAM(this)); } } } @@ -2499,11 +2290,7 @@ { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) -#if _LIBCPP_DEBUG_LEVEL >= 2 - return const_iterator(__nd, this); -#else - return const_iterator(__nd); -#endif + return const_iterator(__nd _LIBCPP_DEBUG_PARAM(this)); } } @@ -2584,16 +2371,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) { __next_pointer __np = __p.__node_; -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container erase(iterator) called with an iterator not" " referring to this container"); - _LIBCPP_ASSERT(__p != end(), + _LIBCPP_DEBUG_ASSERT(__p != end(), "unordered container erase(iterator) called with a non-dereferenceable iterator"); - iterator __r(__np, this); -#else - iterator __r(__np); -#endif + iterator __r(__np _LIBCPP_DEBUG_PARAM(this)); ++__r; remove(__p); return __r; @@ -2604,25 +2388,19 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, + _LIBCPP_DEBUG_ASSERT(__is_valid_iterator(&__first), "unodered container::erase(iterator, iterator) called with an iterator not" " referring to this unodered container"); - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, + _LIBCPP_DEBUG_ASSERT(__is_valid_iterator(&__last), "unodered container::erase(iterator, iterator) called with an iterator not" " referring to this unodered container"); -#endif for (const_iterator __p = __first; __first != __last; __p = __first) { ++__first; erase(__p); } __next_pointer __np = __last.__node_; -#if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator (__np, this); -#else - return iterator (__np); -#endif + return iterator (__np _LIBCPP_DEBUG_PARAM(this)); } template @@ -2689,21 +2467,7 @@ __pn->__next_ = __cn->__next_; __cn->__next_ = nullptr; --size(); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __dp = __c->end_; __dp != __c->beg_; ) - { - --__dp; - iterator* __i = static_cast((*__dp)->__i_); - if (__i->__node_ == __cn) - { - (*__dp)->__c_ = nullptr; - if (--__c->end_ != __dp) - memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif + _LIBCPP_DEBUG_MODE(_DebugBase::__remove_iterators_at_position(__cn, &__iter_to_node_ptr)); return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true)); } @@ -2840,9 +2604,8 @@ if (__u.size() > 0) __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = __u.__p1_.first().__ptr(); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->swap(this, &__u); -#endif + + _DebugBase::__swap_container(std::addressof(__u)); } template Index: include/unordered_map =================================================================== --- include/unordered_map +++ include/unordered_map @@ -904,9 +904,6 @@ unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } explicit unordered_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); @@ -1023,13 +1020,10 @@ {return __table_.__insert_unique(__x);} iterator insert(const_iterator __p, const value_type& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_map::insert(const_iterator, const value_type&) called with an iterator not" " referring to this unordered_map"); -#else ((void)__p); -#endif return insert(__x).first; } @@ -1047,13 +1041,10 @@ {return __table_.__insert_unique(_VSTD::move(__x));} iterator insert(const_iterator __p, value_type&& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_map::insert(const_iterator, const value_type&) called with an iterator not" " referring to this unordered_map"); -#else ((void)__p); -#endif return __table_.__insert_unique(_VSTD::move(__x)).first; } @@ -1068,13 +1059,10 @@ _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, _Pp&& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_map::insert(const_iterator, value_type&&) called with an iterator not" " referring to this unordered_map"); -#else ((void)__p); -#endif return insert(_VSTD::forward<_Pp>(__x)).first; } @@ -1087,13 +1075,10 @@ template _LIBCPP_INLINE_VISIBILITY iterator emplace_hint(const_iterator __p, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_map::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered_map"); -#else ((void)__p); -#endif return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; } @@ -1122,13 +1107,11 @@ _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__h) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__h)), "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" " referring to this unordered_map"); -#else ((void)__h); -#endif + return try_emplace(__k, _VSTD::forward<_Args>(__args)...).first; } @@ -1136,13 +1119,10 @@ _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__h) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__h)), "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" " referring to this unordered_map"); -#else ((void)__h); -#endif return try_emplace(_VSTD::move(__k), _VSTD::forward<_Args>(__args)...).first; } @@ -1334,19 +1314,6 @@ _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} -#if _LIBCPP_DEBUG_LEVEL >= 2 - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(&__i->__i_);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(&__i->__i_);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(&__i->__i_, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(&__i->__i_, __n);} - -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - private: #ifdef _LIBCPP_CXX03_LANG @@ -1426,9 +1393,6 @@ size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -1438,9 +1402,6 @@ const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -1450,9 +1411,6 @@ const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } template @@ -1460,9 +1418,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__first, __last); } @@ -1473,9 +1428,6 @@ const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -1487,9 +1439,6 @@ const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -1499,9 +1448,6 @@ const unordered_map& __u) : __table_(__u.__table_) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1511,9 +1457,6 @@ const unordered_map& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1527,10 +1470,6 @@ _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); - __get_db()->swap(this, &__u); -#endif } template @@ -1538,9 +1477,6 @@ unordered_map&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); @@ -1549,19 +1485,12 @@ __u.__table_.remove((__i++).__i_)->__value_.__move()); } } -#if _LIBCPP_DEBUG_LEVEL >= 2 - else - __get_db()->swap(this, &__u); -#endif } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__il.begin(), __il.end()); } @@ -1571,9 +1500,6 @@ const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -1584,9 +1510,6 @@ const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -1801,9 +1724,6 @@ unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } explicit unordered_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); @@ -2101,21 +2021,6 @@ void rehash(size_type __n) {__table_.rehash(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} - -#if _LIBCPP_DEBUG_LEVEL >= 2 - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(&__i->__i_);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(&__i->__i_);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(&__i->__i_, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(&__i->__i_, __n);} - -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - - }; #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES @@ -2190,9 +2095,6 @@ size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -2202,9 +2104,6 @@ const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -2213,9 +2112,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__first, __last); } @@ -2226,9 +2122,6 @@ const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -2240,9 +2133,6 @@ const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -2253,9 +2143,6 @@ const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } template @@ -2263,9 +2150,6 @@ const unordered_multimap& __u) : __table_(__u.__table_) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -2275,9 +2159,6 @@ const unordered_multimap& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -2291,10 +2172,6 @@ _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); - __get_db()->swap(this, &__u); -#endif } template @@ -2302,9 +2179,6 @@ unordered_multimap&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); @@ -2314,19 +2188,12 @@ __u.__table_.remove((__i++).__i_)->__value_.__move()); } } -#if _LIBCPP_DEBUG_LEVEL >= 2 - else - __get_db()->swap(this, &__u); -#endif } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__il.begin(), __il.end()); } @@ -2336,9 +2203,6 @@ const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -2349,9 +2213,6 @@ const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -423,9 +423,6 @@ unordered_set() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } explicit unordered_set(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); @@ -537,35 +534,27 @@ {return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...);} template _LIBCPP_INLINE_VISIBILITY -#if _LIBCPP_DEBUG_LEVEL >= 2 iterator emplace_hint(const_iterator __p, _Args&&... __args) { - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered_set::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered_set"); + ((void)__p); return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; } -#else - iterator emplace_hint(const_iterator, _Args&&... __args) - {return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first;} -#endif _LIBCPP_INLINE_VISIBILITY pair insert(value_type&& __x) {return __table_.__insert_unique(_VSTD::move(__x));} _LIBCPP_INLINE_VISIBILITY -#if _LIBCPP_DEBUG_LEVEL >= 2 iterator insert(const_iterator __p, value_type&& __x) { - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_set::insert(const_iterator, value_type&&) called with an iterator not" " referring to this unordered_set"); + ((void)__p); return insert(_VSTD::move(__x)).first; } -#else - iterator insert(const_iterator, value_type&& __x) - {return insert(_VSTD::move(__x)).first;} -#endif _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} @@ -575,18 +564,15 @@ {return __table_.__insert_unique(__x);} _LIBCPP_INLINE_VISIBILITY -#if _LIBCPP_DEBUG_LEVEL >= 2 iterator insert(const_iterator __p, const value_type& __x) { - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + _LIBCPP_DEBUG_ASSERT(__table_.__is_valid_iterator(std::addressof(__p)), "unordered_set::insert(const_iterator, const value_type&) called with an iterator not" " referring to this unordered_set"); + ((void)__p); return insert(__x).first; } -#else - iterator insert(const_iterator, const value_type& __x) - {return insert(__x).first;} -#endif + template _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); @@ -723,20 +709,6 @@ void rehash(size_type __n) {__table_.rehash(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} - -#if _LIBCPP_DEBUG_LEVEL >= 2 - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(__i);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(__i);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - }; #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES @@ -800,9 +772,6 @@ const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -811,9 +780,6 @@ const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -822,9 +788,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( _InputIterator __first, _InputIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__first, __last); } @@ -835,9 +798,6 @@ const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -849,9 +809,6 @@ const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -862,9 +819,6 @@ const allocator_type& __a) : __table_(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } template @@ -872,9 +826,6 @@ const unordered_set& __u) : __table_(__u.__table_) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -884,9 +835,6 @@ const unordered_set& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -900,10 +848,6 @@ _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); - __get_db()->swap(this, &__u); -#endif } template @@ -911,28 +855,18 @@ unordered_set&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) __table_.__insert_unique(_VSTD::move(__u.__table_.remove(__i++)->__value_)); } -#if _LIBCPP_DEBUG_LEVEL >= 2 - else - __get_db()->swap(this, &__u); -#endif } template unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( initializer_list __il) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__il.begin(), __il.end()); } @@ -942,9 +876,6 @@ const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -955,9 +886,6 @@ const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -1085,9 +1013,6 @@ unordered_multiset() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } explicit unordered_multiset(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); @@ -1354,20 +1279,6 @@ void rehash(size_type __n) {__table_.rehash(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} - -#if _LIBCPP_DEBUG_LEVEL >= 2 - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(__i);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(__i);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - -#endif // _LIBCPP_DEBUG_LEVEL >= 2 - }; #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES @@ -1429,9 +1340,6 @@ size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -1441,9 +1349,6 @@ const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); } @@ -1452,9 +1357,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( _InputIterator __first, _InputIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__first, __last); } @@ -1465,9 +1367,6 @@ const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -1479,9 +1378,6 @@ const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__first, __last); } @@ -1492,9 +1388,6 @@ const allocator_type& __a) : __table_(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } template @@ -1502,9 +1395,6 @@ const unordered_multiset& __u) : __table_(__u.__table_) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1514,9 +1404,6 @@ const unordered_multiset& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1530,10 +1417,6 @@ _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); - __get_db()->swap(this, &__u); -#endif } template @@ -1541,28 +1424,18 @@ unordered_multiset&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) __table_.__insert_multi(_VSTD::move(__u.__table_.remove(__i++)->__value_)); } -#if _LIBCPP_DEBUG_LEVEL >= 2 - else - __get_db()->swap(this, &__u); -#endif } template unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( initializer_list __il) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif insert(__il.begin(), __il.end()); } @@ -1572,9 +1445,6 @@ const key_equal& __eql) : __table_(__hf, __eql) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } @@ -1585,9 +1455,6 @@ const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -323,7 +323,8 @@ template class __vector_base - : protected __vector_base_common + : protected __vector_base_common, + protected __container_debug_base< vector<_Tp, _Allocator> > { public: typedef _Allocator allocator_type; @@ -339,6 +340,8 @@ typedef pointer iterator; typedef const_pointer const_iterator; + typedef __container_debug_base< vector<_Tp, _Allocator> > _DebugBase; + pointer __begin_; pointer __end_; __compressed_pair __end_cap_; @@ -472,6 +475,8 @@ private: typedef __vector_base<_Tp, _Allocator> __base; typedef allocator<_Tp> __default_allocator_type; + using typename __base::_DebugBase; + public: typedef vector __self; typedef _Tp value_type; @@ -494,9 +499,6 @@ _LIBCPP_INLINE_VISIBILITY vector() _NOEXCEPT_(is_nothrow_default_constructible::value) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 @@ -506,9 +508,6 @@ #endif : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif } explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 @@ -549,9 +548,6 @@ ~vector() { __annotate_delete(); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__erase_c(this); -#endif } vector(const vector& __x); @@ -771,7 +767,7 @@ size_type __old_size = size(); __base::clear(); __annotate_shrink(__old_size); - __invalidate_all_iterators(); + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); } void resize(size_type __sz); @@ -797,8 +793,15 @@ #endif // _LIBCPP_DEBUG_LEVEL >= 2 private: - _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); - _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(pointer __new_last); + static _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE const_pointer __convert_iter(void* __p) _NOEXCEPT +#if _LIBCPP_DEBUG_LEVEL >= 2 + { + return static_cast(__p)->base(); + } +#else + = delete; +#endif + void __vallocate(size_type __n); void __vdeallocate() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; @@ -828,7 +831,7 @@ _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last) _NOEXCEPT { - __invalidate_iterators_past(__new_last); + _LIBCPP_DEBUG_MODE(_DebugBase::__remove_iterators_past(__new_last, __convert_iter)); size_type __old_size = size(); __base::__destruct_at_end(__new_last); __annotate_shrink(__old_size); @@ -954,7 +957,7 @@ _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); - __invalidate_all_iterators(); + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); } template @@ -970,7 +973,7 @@ _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); - __invalidate_all_iterators(); + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); return __r; } @@ -1113,9 +1116,6 @@ template vector<_Tp, _Allocator>::vector(size_type __n) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__n > 0) { __vallocate(__n); @@ -1128,9 +1128,6 @@ vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__n > 0) { __vallocate(__n); @@ -1142,9 +1139,6 @@ template vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__n > 0) { __vallocate(__n); @@ -1156,9 +1150,6 @@ vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__n > 0) { __vallocate(__n); @@ -1176,9 +1167,6 @@ typename iterator_traits<_InputIterator>::reference>::value, _InputIterator>::type __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif for (; __first != __last; ++__first) __emplace_back(*__first); } @@ -1193,9 +1181,6 @@ typename iterator_traits<_InputIterator>::reference>::value>::type*) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif for (; __first != __last; ++__first) __emplace_back(*__first); } @@ -1209,9 +1194,6 @@ typename iterator_traits<_ForwardIterator>::reference>::value, _ForwardIterator>::type __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif size_type __n = static_cast(_VSTD::distance(__first, __last)); if (__n > 0) { @@ -1229,9 +1211,6 @@ typename iterator_traits<_ForwardIterator>::reference>::value>::type*) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif size_type __n = static_cast(_VSTD::distance(__first, __last)); if (__n > 0) { @@ -1244,9 +1223,6 @@ vector<_Tp, _Allocator>::vector(const vector& __x) : __base(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif size_type __n = __x.size(); if (__n > 0) { @@ -1259,9 +1235,6 @@ vector<_Tp, _Allocator>::vector(const vector& __x, const allocator_type& __a) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif size_type __n = __x.size(); if (__n > 0) { @@ -1282,10 +1255,7 @@ #endif : __base(_VSTD::move(__x.__alloc())) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); - __get_db()->swap(this, &__x); -#endif + _DebugBase::__swap_container(std::addressof(__x)); this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); @@ -1297,18 +1267,13 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const allocator_type& __a) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__a == __x.__alloc()) { this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->swap(this, &__x); -#endif + _DebugBase::__swap_container(std::addressof(__x)); } else { @@ -1321,9 +1286,6 @@ inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__il.size() > 0) { __vallocate(__il.size()); @@ -1336,9 +1298,6 @@ vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __base(__a) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif if (__il.size() > 0) { __vallocate(__il.size()); @@ -1382,9 +1341,7 @@ this->__end_ = __c.__end_; this->__end_cap() = __c.__end_cap(); __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->swap(this, &__c); -#endif + _DebugBase::__swap_container(std::addressof(__c)); } #endif // !_LIBCPP_CXX03_LANG @@ -1455,7 +1412,7 @@ __vallocate(__recommend(__new_size)); __construct_at_end(__first, __last, __new_size); } - __invalidate_all_iterators(); + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); } template @@ -1477,7 +1434,7 @@ __vallocate(__recommend(static_cast(__n))); __construct_at_end(__n, __u); } - __invalidate_all_iterators(); + _LIBCPP_DEBUG_MODE(_DebugBase::__invalidate_all_iterators()); } template @@ -1701,17 +1658,15 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::erase(iterator) called with an iterator not" " referring to this vector"); -#endif _LIBCPP_ASSERT(__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p)); - this->__invalidate_iterators_past(__p-1); + _LIBCPP_DEBUG_MODE(_DebugBase::__remove_iterators_past(__p-1, __convert_iter)); iterator __r = __make_iter(__p); return __r; } @@ -1720,19 +1675,17 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__first)), "vector::erase(iterator, iterator) called with an iterator not" " referring to this vector"); - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__last)), "vector::erase(iterator, iterator) called with an iterator not" " referring to this vector"); -#endif _LIBCPP_ASSERT(__first <= __last, "vector::erase(first, last) called with invalid range"); pointer __p = this->__begin_ + (__first - begin()); if (__first != __last) { this->__destruct_at_end(_VSTD::move(__p + (__last - __first), this->__end_, __p)); - this->__invalidate_iterators_past(__p - 1); + _LIBCPP_DEBUG_MODE(_DebugBase::__remove_iterators_past(__p-1, __convert_iter)); } iterator __r = __make_iter(__p); return __r; @@ -1760,11 +1713,9 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::insert(iterator, x) called with an iterator not" " referring to this vector"); -#endif pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { @@ -1797,11 +1748,9 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::insert(iterator, x) called with an iterator not" " referring to this vector"); -#endif pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { @@ -1830,11 +1779,9 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::emplace(iterator, x) called with an iterator not" " referring to this vector"); -#endif pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { @@ -1865,11 +1812,9 @@ typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::insert(iterator, n, x) called with an iterator not" " referring to this vector"); -#endif pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { @@ -1916,11 +1861,9 @@ >::type vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::insert(iterator, range) called with an iterator not" " referring to this vector"); -#endif difference_type __off = __position - begin(); pointer __p = this->__begin_ + __off; allocator_type& __a = this->__alloc(); @@ -1969,11 +1912,9 @@ >::type vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this, + _LIBCPP_DEBUG_ASSERT(_DebugBase::__is_valid_iterator(std::addressof(__position)), "vector::insert(iterator, range) called with an iterator not" " referring to this vector"); -#endif pointer __p = this->__begin_ + (__position - begin()); difference_type __n = _VSTD::distance(__first, __last); if (__n > 0) @@ -2050,9 +1991,7 @@ _VSTD::swap(this->__end_cap(), __x.__end_cap()); __swap_allocator(this->__alloc(), __x.__alloc(), integral_constant()); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->swap(this, &__x); -#endif // _LIBCPP_DEBUG_LEVEL >= 2 + _DebugBase::__swap_container(std::addressof(__x)); } template @@ -2110,37 +2049,6 @@ #endif // _LIBCPP_DEBUG_LEVEL >= 2 -template -inline _LIBCPP_INLINE_VISIBILITY -void -vector<_Tp, _Allocator>::__invalidate_all_iterators() -{ -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__invalidate_all(this); -#endif // _LIBCPP_DEBUG_LEVEL >= 2 -} - - -template -inline _LIBCPP_INLINE_VISIBILITY -void -vector<_Tp, _Allocator>::__invalidate_iterators_past(pointer __new_last) { -#if _LIBCPP_DEBUG_LEVEL >= 2 - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) { - --__p; - const_iterator* __i = static_cast((*__p)->__i_); - if (__i->base() > __new_last) { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#else - ((void)__new_last); -#endif -} // vector @@ -2425,7 +2333,6 @@ bool __invariants() const; private: - _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); void __vallocate(size_type __n); void __vdeallocate() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY @@ -2505,12 +2412,6 @@ friend struct _LIBCPP_TEMPLATE_VIS hash; }; -template -inline _LIBCPP_INLINE_VISIBILITY -void -vector::__invalidate_all_iterators() -{ -} // Allocate space for __n objects // throws length_error if __n > max_size() @@ -2538,7 +2439,6 @@ if (this->__begin_ != nullptr) { __storage_traits::deallocate(this->__alloc(), this->__begin_, __cap()); - __invalidate_all_iterators(); this->__begin_ = nullptr; this->__size_ = this->__cap() = 0; } @@ -2711,7 +2611,6 @@ { if (__begin_ != nullptr) __storage_traits::deallocate(__alloc(), __begin_, __cap()); - __invalidate_all_iterators(); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2738,7 +2637,6 @@ { if (__begin_ != nullptr) __storage_traits::deallocate(__alloc(), __begin_, __cap()); - __invalidate_all_iterators(); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2813,7 +2711,6 @@ { if (__begin_ != nullptr) __storage_traits::deallocate(__alloc(), __begin_, __cap()); - __invalidate_all_iterators(); } template @@ -2957,7 +2854,6 @@ } _VSTD::fill_n(begin(), __n, __x); } - __invalidate_all_iterators(); } template @@ -3009,7 +2905,6 @@ __v.__vallocate(__n); __v.__construct_at_end(this->begin(), this->end()); swap(__v); - __invalidate_all_iterators(); } } Index: test/libcxx/debug/containers/db_unord_container_tests.pass.cpp =================================================================== --- test/libcxx/debug/containers/db_unord_container_tests.pass.cpp +++ test/libcxx/debug/containers/db_unord_container_tests.pass.cpp @@ -15,10 +15,14 @@ // UNSUPPORTED: with_system_cxx_lib // test container debugging - +#if defined(__DEPRECATED) +#undef __DEPRECATED +#endif #define _LIBCPP_DEBUG 1 #include #include +#include +#include #include #include #include "container_debug_tests.h" @@ -62,6 +66,12 @@ UnorderedContainerChecks< std::unordered_multiset, std::equal_to, SetAlloc>, CT_UnorderedMultiSet>::run(); + UnorderedContainerChecks< + __gnu_cxx::hash_multiset, std::equal_to, SetAlloc>, + CT_GnuHashMultiSet>::run(); + UnorderedContainerChecks< + __gnu_cxx::hash_multimap, std::equal_to, MapAlloc>, + CT_GnuHashMultiMap>::run(); } return 0; Index: test/support/container_debug_tests.h =================================================================== --- test/support/container_debug_tests.h +++ test/support/container_debug_tests.h @@ -59,7 +59,11 @@ CT_UnorderedMap, CT_UnorderedSet, CT_UnorderedMultiMap, - CT_UnorderedMultiSet + CT_UnorderedMultiSet, + CT_GnuHashMap, + CT_GnuHashSet, + CT_GnuHashMultiMap, + CT_GnuHashMultiSet, }; constexpr bool isSequential(ContainerType CT) { @@ -71,28 +75,41 @@ } constexpr bool isUnordered(ContainerType CT) { - return CT_UnorderedMap >= CT && CT_UnorderedMultiSet <= CT; + return CT_UnorderedMap >= CT && CT_GnuHashSet <= CT; } constexpr bool isSet(ContainerType CT) { return CT == CT_Set || CT == CT_MultiSet || CT == CT_UnorderedSet - || CT == CT_UnorderedMultiSet; + || CT == CT_UnorderedMultiSet + || CT == CT_GnuHashSet + || CT == CT_GnuHashMultiSet; } constexpr bool isMap(ContainerType CT) { return CT == CT_Map || CT == CT_MultiMap || CT == CT_UnorderedMap - || CT == CT_UnorderedMultiMap; + || CT == CT_UnorderedMultiMap + || CT == CT_GnuHashMap + || CT == CT_GnuHashMultiMap; } constexpr bool isMulti(ContainerType CT) { return CT == CT_MultiMap || CT == CT_MultiSet || CT == CT_UnorderedMultiMap - || CT == CT_UnorderedMultiSet; + || CT == CT_UnorderedMultiSet + || CT == CT_GnuHashMultiMap + || CT == CT_GnuHashMultiSet; +} + +constexpr bool isGnu(ContainerType CT) { + return CT == CT_GnuHashSet + || CT == CT_GnuHashMap + || CT == CT_GnuHashMultiSet + || CT == CT_GnuHashMultiMap; } template @@ -173,8 +190,16 @@ } } + static Container makeContainerImpl(allocator_type A) { + if constexpr (isGnu(CT)) { + return Container(5, typename Container::hasher{}, typename Container::key_equal{}, A); + } else { + return Container(A); + } + } + static Container makeContainer(int size, allocator_type A = allocator_type()) { - Container C(A); + Container C = makeContainerImpl(A); if constexpr (CT == CT_ForwardList) { for (int i = 0; i < size; ++i) C.insert_after(C.before_begin(), Helper::makeValueType(i)); @@ -239,8 +264,14 @@ static void DerefEndIterator() { CHECKPOINT("testing deref end iterator"); Container C = makeContainer(1); + const Container &CC = C; iterator i = C.begin(); - const_iterator ci = C.cbegin(); + const_iterator ci; + if constexpr (isGnu(CT)) { + ci = CC.begin(); + } else { + ci = C.cbegin(); + } (void)*i; (void)*ci; if constexpr (CT != CT_VectorBool) { i.operator->(); @@ -279,6 +310,9 @@ static void MoveInvalidatesIterators() { CHECKPOINT("copy move invalidates iterators"); + if (isGnu(CT)) { + return; // GNU containers don't have move constructors + } Container C1 = makeContainer(3); iterator i = C1.begin(); Container C2 = std::move(C1);