[libcxx] r276003 - Fix undefined behavior in __tree
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 19 11:06:34 PDT 2016
@Hans. This needs to be merged into 3.9. It fixes PR28469 which is a
release blocker.
On Tue, Jul 19, 2016 at 11:56 AM, Eric Fiselier via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: ericwf
> Date: Tue Jul 19 12:56:20 2016
> New Revision: 276003
>
> URL: http://llvm.org/viewvc/llvm-project?rev=276003&view=rev
> Log:
> Fix undefined behavior in __tree
>
> Summary:
> This patch attempts to fix the undefined behavior in __tree by changing
> the node pointer types used throughout. The pointer types are changed for
> raw pointers in the current ABI and for fancy pointers in ABI V2 (since the
> fancy pointer types may not be ABI compatible).
>
> The UB in `__tree` arises because tree downcasts the embedded end node and
> then deferences that pointer. Currently there are 3 node types in __tree.
>
> * `__tree_end_node` which contains the `__left_` pointer. This node is
> embedded within the container.
> * `__tree_node_base` which contains `__right_`, `__parent_` and
> `__is_black`. This node is used throughout the tree rebalancing algorithms.
> * `__tree_node` which contains `__value_`.
>
> Currently `__tree` stores the start of the tree, `__begin_node_`, as a
> pointer to a `__tree_node`. Additionally the iterators store their position
> as a pointer to a `__tree_node`. In both of these cases the pointee can be
> the end node. This is fixed by changing them to store `__tree_end_node`
> pointers instead.
>
> To make this change I introduced an `__iter_pointer` typedef which is
> defined to be a pointer to either `__tree_end_node` in the new ABI or
> `__tree_node` in the current one.
> Both `__tree::__begin_node_` and iterator pointers are now stored as
> `__iter_pointers`.
>
> The other situation where `__tree_end_node` is stored as the wrong type is
> in `__tree_node_base::__parent_`. Currently `__left_`, `__right_`, and
> `__parent_` are all `__tree_node_base` pointers. Since the end node will
> only be stored in `__parent_` the fix is to change `__parent_` to be a
> pointer to `__tree_end_node`.
>
> To make this change I introduced a `__parent_pointer` typedef which is
> defined to be a pointer to either `__tree_end_node` in the new ABI or
> `__tree_node_base` in the current one.
>
> Note that in the new ABI `__iter_pointer` and `__parent_pointer` are the
> same type (but not in the old one). The confusion between these two types
> is unfortunate but it was the best solution I could come up with that
> maintains the ABI.
>
> The typedef changes force a ton of explicit type casts to correct pointer
> types and to make current code compatible with both the old and new pointer
> typedefs. This is the bulk of the change and it's really messy.
> Unfortunately I don't know how to avoid it.
>
> Please let me know what you think.
>
>
>
>
>
> Reviewers: howard.hinnant, mclow.lists
>
> Subscribers: howard.hinnant, bbannier, cfe-commits
>
> Differential Revision: https://reviews.llvm.org/D20786
>
> Added:
>
> libcxx/trunk/test/std/containers/associative/map/PR28469_undefined_behavior_segfault.sh.cpp
> Modified:
> libcxx/trunk/include/__config
> libcxx/trunk/include/__tree
>
> libcxx/trunk/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp
>
> libcxx/trunk/test/libcxx/containers/associative/tree_left_rotate.pass.cpp
> libcxx/trunk/test/libcxx/containers/associative/tree_remove.pass.cpp
>
> libcxx/trunk/test/libcxx/containers/associative/tree_right_rotate.pass.cpp
> libcxx/trunk/test/ubsan_blacklist.txt
>
> Modified: libcxx/trunk/include/__config
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> --- libcxx/trunk/include/__config (original)
> +++ libcxx/trunk/include/__config Tue Jul 19 12:56:20 2016
> @@ -41,6 +41,8 @@
> #define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
> // Fix undefined behavior in how std::list stores it's linked nodes.
> #define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
> +// Fix undefined behavior in how __tree stores its end and parent nodes.
> +#define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
> #define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
> #define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
> #define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
>
> Modified: libcxx/trunk/include/__tree
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tree?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> --- libcxx/trunk/include/__tree (original)
> +++ libcxx/trunk/include/__tree Tue Jul 19 12:56:20 2016
> @@ -165,21 +165,36 @@ __tree_next(_NodePtr __x) _NOEXCEPT
> if (__x->__right_ != nullptr)
> return __tree_min(__x->__right_);
> while (!__tree_is_left_child(__x))
> - __x = __x->__parent_;
> - return __x->__parent_;
> + __x = __x->__parent_unsafe();
> + return __x->__parent_unsafe();
> +}
> +
> +template <class _EndNodePtr, class _NodePtr>
> +inline _LIBCPP_INLINE_VISIBILITY
> +_EndNodePtr
> +__tree_next_iter(_NodePtr __x) _NOEXCEPT
> +{
> + if (__x->__right_ != nullptr)
> + return static_cast<_EndNodePtr>(__tree_min(__x->__right_));
> + while (!__tree_is_left_child(__x))
> + __x = __x->__parent_unsafe();
> + return static_cast<_EndNodePtr>(__x->__parent_);
> }
>
> // Returns: pointer to the previous in-order node before __x.
> // Precondition: __x != nullptr.
> -template <class _NodePtr>
> +// Note: __x may be the end node.
> +template <class _NodePtr, class _EndNodePtr>
> +inline _LIBCPP_INLINE_VISIBILITY
> _NodePtr
> -__tree_prev(_NodePtr __x) _NOEXCEPT
> +__tree_prev_iter(_EndNodePtr __x) _NOEXCEPT
> {
> if (__x->__left_ != nullptr)
> return __tree_max(__x->__left_);
> - while (__tree_is_left_child(__x))
> - __x = __x->__parent_;
> - return __x->__parent_;
> + _NodePtr __xx = static_cast<_NodePtr>(__x);
> + while (__tree_is_left_child(__xx))
> + __xx = __xx->__parent_unsafe();
> + return __xx->__parent_unsafe();
> }
>
> // Returns: pointer to a node which has no children
> @@ -215,14 +230,14 @@ __tree_left_rotate(_NodePtr __x) _NOEXCE
> _NodePtr __y = __x->__right_;
> __x->__right_ = __y->__left_;
> if (__x->__right_ != nullptr)
> - __x->__right_->__parent_ = __x;
> + __x->__right_->__set_parent(__x);
> __y->__parent_ = __x->__parent_;
> if (__tree_is_left_child(__x))
> __x->__parent_->__left_ = __y;
> else
> - __x->__parent_->__right_ = __y;
> + __x->__parent_unsafe()->__right_ = __y;
> __y->__left_ = __x;
> - __x->__parent_ = __y;
> + __x->__set_parent(__y);
> }
>
> // Effects: Makes __x->__left_ the subtree root with __x as its right
> child
> @@ -235,14 +250,14 @@ __tree_right_rotate(_NodePtr __x) _NOEXC
> _NodePtr __y = __x->__left_;
> __x->__left_ = __y->__right_;
> if (__x->__left_ != nullptr)
> - __x->__left_->__parent_ = __x;
> + __x->__left_->__set_parent(__x);
> __y->__parent_ = __x->__parent_;
> if (__tree_is_left_child(__x))
> __x->__parent_->__left_ = __y;
> else
> - __x->__parent_->__right_ = __y;
> + __x->__parent_unsafe()->__right_ = __y;
> __y->__right_ = __x;
> - __x->__parent_ = __y;
> + __x->__set_parent(__y);
> }
>
> // Effects: Rebalances __root after attaching __x to a leaf.
> @@ -258,17 +273,17 @@ void
> __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT
> {
> __x->__is_black_ = __x == __root;
> - while (__x != __root && !__x->__parent_->__is_black_)
> + while (__x != __root && !__x->__parent_unsafe()->__is_black_)
> {
> // __x->__parent_ != __root because __x->__parent_->__is_black ==
> false
> - if (__tree_is_left_child(__x->__parent_))
> + if (__tree_is_left_child(__x->__parent_unsafe()))
> {
> - _NodePtr __y = __x->__parent_->__parent_->__right_;
> + _NodePtr __y =
> __x->__parent_unsafe()->__parent_unsafe()->__right_;
> if (__y != nullptr && !__y->__is_black_)
> {
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = true;
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = __x == __root;
> __y->__is_black_ = true;
> }
> @@ -276,12 +291,12 @@ __tree_balance_after_insert(_NodePtr __r
> {
> if (!__tree_is_left_child(__x))
> {
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __tree_left_rotate(__x);
> }
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = true;
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = false;
> __tree_right_rotate(__x);
> break;
> @@ -289,12 +304,12 @@ __tree_balance_after_insert(_NodePtr __r
> }
> else
> {
> - _NodePtr __y = __x->__parent_->__parent_->__left_;
> + _NodePtr __y = __x->__parent_unsafe()->__parent_->__left_;
> if (__y != nullptr && !__y->__is_black_)
> {
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = true;
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = __x == __root;
> __y->__is_black_ = true;
> }
> @@ -302,12 +317,12 @@ __tree_balance_after_insert(_NodePtr __r
> {
> if (__tree_is_left_child(__x))
> {
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __tree_right_rotate(__x);
> }
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = true;
> - __x = __x->__parent_;
> + __x = __x->__parent_unsafe();
> __x->__is_black_ = false;
> __tree_left_rotate(__x);
> break;
> @@ -344,13 +359,13 @@ __tree_remove(_NodePtr __root, _NodePtr
> {
> __y->__parent_->__left_ = __x;
> if (__y != __root)
> - __w = __y->__parent_->__right_;
> + __w = __y->__parent_unsafe()->__right_;
> else
> __root = __x; // __w == nullptr
> }
> else
> {
> - __y->__parent_->__right_ = __x;
> + __y->__parent_unsafe()->__right_ = __x;
> // __y can't be root if it is a right child
> __w = __y->__parent_->__left_;
> }
> @@ -364,12 +379,12 @@ __tree_remove(_NodePtr __root, _NodePtr
> if (__tree_is_left_child(__z))
> __y->__parent_->__left_ = __y;
> else
> - __y->__parent_->__right_ = __y;
> + __y->__parent_unsafe()->__right_ = __y;
> __y->__left_ = __z->__left_;
> - __y->__left_->__parent_ = __y;
> + __y->__left_->__set_parent(__y);
> __y->__right_ = __z->__right_;
> if (__y->__right_ != nullptr)
> - __y->__right_->__parent_ = __y;
> + __y->__right_->__set_parent(__y);
> __y->__is_black_ = __z->__is_black_;
> if (__root == __z)
> __root = __y;
> @@ -406,8 +421,8 @@ __tree_remove(_NodePtr __root, _NodePtr
> if (!__w->__is_black_)
> {
> __w->__is_black_ = true;
> - __w->__parent_->__is_black_ = false;
> - __tree_left_rotate(__w->__parent_);
> + __w->__parent_unsafe()->__is_black_ = false;
> + __tree_left_rotate(__w->__parent_unsafe());
> // __x is still valid
> // reset __root only if necessary
> if (__root == __w->__left_)
> @@ -420,7 +435,7 @@ __tree_remove(_NodePtr __root, _NodePtr
> (__w->__right_ == nullptr ||
> __w->__right_->__is_black_))
> {
> __w->__is_black_ = false;
> - __x = __w->__parent_;
> + __x = __w->__parent_unsafe();
> // __x can no longer be null
> if (__x == __root || !__x->__is_black_)
> {
> @@ -429,7 +444,7 @@ __tree_remove(_NodePtr __root, _NodePtr
> }
> // reset sibling, and it still can't be null
> __w = __tree_is_left_child(__x) ?
> - __x->__parent_->__right_ :
> + __x->__parent_unsafe()->__right_ :
> __x->__parent_->__left_;
> // continue;
> }
> @@ -443,13 +458,13 @@ __tree_remove(_NodePtr __root, _NodePtr
> __tree_right_rotate(__w);
> // __w is known not to be root, so root
> hasn't changed
> // reset sibling, and it still can't be null
> - __w = __w->__parent_;
> + __w = __w->__parent_unsafe();
> }
> // __w has a right red child, left child may be
> null
> - __w->__is_black_ = __w->__parent_->__is_black_;
> - __w->__parent_->__is_black_ = true;
> + __w->__is_black_ =
> __w->__parent_unsafe()->__is_black_;
> + __w->__parent_unsafe()->__is_black_ = true;
> __w->__right_->__is_black_ = true;
> - __tree_left_rotate(__w->__parent_);
> + __tree_left_rotate(__w->__parent_unsafe());
> break;
> }
> }
> @@ -458,8 +473,8 @@ __tree_remove(_NodePtr __root, _NodePtr
> if (!__w->__is_black_)
> {
> __w->__is_black_ = true;
> - __w->__parent_->__is_black_ = false;
> - __tree_right_rotate(__w->__parent_);
> + __w->__parent_unsafe()->__is_black_ = false;
> + __tree_right_rotate(__w->__parent_unsafe());
> // __x is still valid
> // reset __root only if necessary
> if (__root == __w->__right_)
> @@ -472,7 +487,7 @@ __tree_remove(_NodePtr __root, _NodePtr
> (__w->__right_ == nullptr ||
> __w->__right_->__is_black_))
> {
> __w->__is_black_ = false;
> - __x = __w->__parent_;
> + __x = __w->__parent_unsafe();
> // __x can no longer be null
> if (!__x->__is_black_ || __x == __root)
> {
> @@ -481,7 +496,7 @@ __tree_remove(_NodePtr __root, _NodePtr
> }
> // reset sibling, and it still can't be null
> __w = __tree_is_left_child(__x) ?
> - __x->__parent_->__right_ :
> + __x->__parent_unsafe()->__right_ :
> __x->__parent_->__left_;
> // continue;
> }
> @@ -495,13 +510,13 @@ __tree_remove(_NodePtr __root, _NodePtr
> __tree_left_rotate(__w);
> // __w is known not to be root, so root
> hasn't changed
> // reset sibling, and it still can't be null
> - __w = __w->__parent_;
> + __w = __w->__parent_unsafe();
> }
> // __w has a left red child, right child may be
> null
> - __w->__is_black_ = __w->__parent_->__is_black_;
> - __w->__parent_->__is_black_ = true;
> + __w->__is_black_ =
> __w->__parent_unsafe()->__is_black_;
> + __w->__parent_unsafe()->__is_black_ = true;
> __w->__left_->__is_black_ = true;
> - __tree_right_rotate(__w->__parent_);
> + __tree_right_rotate(__w->__parent_unsafe());
> break;
> }
> }
> @@ -617,6 +632,15 @@ struct __tree_node_base_types {
> typedef __tree_end_node<__node_base_pointer>
> __end_node_type;
> typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type
>
> __end_node_pointer;
> +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB)
> + typedef __end_node_pointer __parent_pointer;
> +#else
> + typedef typename conditional<
> + is_pointer<__end_node_pointer>::value,
> + __end_node_pointer,
> + __node_base_pointer>::type __parent_pointer;
> +#endif
> +
> private:
> static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type,
> void>::value),
> "_VoidPtr does not point to unqualified void type");
> @@ -657,6 +681,14 @@ public:
>
> __node_value_type_pointer;
> typedef typename __rebind_pointer<_VoidPtr, const
> __node_value_type>::type
>
> __const_node_value_type_pointer;
> +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB)
> + typedef typename __base::__end_node_pointer __iter_pointer;
> +#else
> + typedef typename conditional<
> + is_pointer<__node_pointer>::value,
> + typename __base::__end_node_pointer,
> + __node_pointer>::type __iter_pointer;
> +#endif
> private:
> static_assert(!is_const<__node_type>::value,
> "_NodePtr should never be a pointer to const");
> @@ -692,11 +724,20 @@ class __tree_node_base
>
> public:
> typedef typename _NodeBaseTypes::__node_base_pointer pointer;
> + typedef typename _NodeBaseTypes::__parent_pointer __parent_pointer;
>
> - pointer __right_;
> - pointer __parent_;
> + pointer __right_;
> + __parent_pointer __parent_;
> bool __is_black_;
>
> + _LIBCPP_INLINE_VISIBILITY
> + pointer __parent_unsafe() const { return
> static_cast<pointer>(__parent_);}
> +
> + _LIBCPP_INLINE_VISIBILITY
> + void __set_parent(pointer __p) {
> + __parent_ = static_cast<__parent_pointer>(__p);
> + }
> +
> private:
> ~__tree_node_base() _LIBCPP_EQUAL_DELETE;
> __tree_node_base(__tree_node_base const&) _LIBCPP_EQUAL_DELETE;
> @@ -761,9 +802,11 @@ class _LIBCPP_TYPE_VIS_ONLY __tree_itera
> typedef __tree_node_types<_NodePtr> _NodeTypes;
> typedef _NodePtr
> __node_pointer;
> typedef typename _NodeTypes::__node_base_pointer
> __node_base_pointer;
> + typedef typename _NodeTypes::__end_node_pointer
> __end_node_pointer;
> + typedef typename _NodeTypes::__iter_pointer
> __iter_pointer;
> typedef pointer_traits<__node_pointer> __pointer_traits;
>
> - __node_pointer __ptr_;
> + __iter_pointer __ptr_;
>
> public:
> typedef bidirectional_iterator_tag
> iterator_category;
> @@ -778,14 +821,15 @@ public:
> #endif
> {}
>
> - _LIBCPP_INLINE_VISIBILITY reference operator*() const {return
> __ptr_->__value_;}
> + _LIBCPP_INLINE_VISIBILITY reference operator*() const
> + {return __get_np()->__value_;}
> _LIBCPP_INLINE_VISIBILITY pointer operator->() const
> - {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
> + {return
> pointer_traits<pointer>::pointer_to(__get_np()->__value_);}
>
> _LIBCPP_INLINE_VISIBILITY
> __tree_iterator& operator++() {
> - __ptr_ = static_cast<__node_pointer>(
> - __tree_next(static_cast<__node_base_pointer>(__ptr_)));
> + __ptr_ = static_cast<__iter_pointer>(
> +
> __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)));
> return *this;
> }
> _LIBCPP_INLINE_VISIBILITY
> @@ -794,8 +838,8 @@ public:
>
> _LIBCPP_INLINE_VISIBILITY
> __tree_iterator& operator--() {
> - __ptr_ = static_cast<__node_pointer>(
> - __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
> + __ptr_ =
> static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>(
> + static_cast<__end_node_pointer>(__ptr_)));
> return *this;
> }
> _LIBCPP_INLINE_VISIBILITY
> @@ -812,6 +856,10 @@ public:
> private:
> _LIBCPP_INLINE_VISIBILITY
> explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p)
> {}
> + _LIBCPP_INLINE_VISIBILITY
> + explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT :
> __ptr_(__p) {}
> + _LIBCPP_INLINE_VISIBILITY
> + __node_pointer __get_np() const { return
> static_cast<__node_pointer>(__ptr_); }
> template <class, class, class> friend class __tree;
> template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY
> __tree_const_iterator;
> template <class> friend class _LIBCPP_TYPE_VIS_ONLY __map_iterator;
> @@ -827,9 +875,11 @@ class _LIBCPP_TYPE_VIS_ONLY __tree_const
> typedef __tree_node_types<_NodePtr> _NodeTypes;
> typedef typename _NodeTypes::__node_pointer
> __node_pointer;
> typedef typename _NodeTypes::__node_base_pointer
> __node_base_pointer;
> + typedef typename _NodeTypes::__end_node_pointer
> __end_node_pointer;
> + typedef typename _NodeTypes::__iter_pointer
> __iter_pointer;
> typedef pointer_traits<__node_pointer> __pointer_traits;
>
> - __node_pointer __ptr_;
> + __iter_pointer __ptr_;
>
> public:
> typedef bidirectional_iterator_tag
> iterator_category;
> @@ -852,14 +902,15 @@ public:
> __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT
> : __ptr_(__p.__ptr_) {}
>
> - _LIBCPP_INLINE_VISIBILITY reference operator*() const {return
> __ptr_->__value_;}
> + _LIBCPP_INLINE_VISIBILITY reference operator*() const
> + {return __get_np()->__value_;}
> _LIBCPP_INLINE_VISIBILITY pointer operator->() const
> - {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);}
> + {return
> pointer_traits<pointer>::pointer_to(__get_np()->__value_);}
>
> _LIBCPP_INLINE_VISIBILITY
> __tree_const_iterator& operator++() {
> - __ptr_ = static_cast<__node_pointer>(
> - __tree_next(static_cast<__node_base_pointer>(__ptr_)));
> + __ptr_ = static_cast<__iter_pointer>(
> +
> __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)));
> return *this;
> }
>
> @@ -869,8 +920,8 @@ public:
>
> _LIBCPP_INLINE_VISIBILITY
> __tree_const_iterator& operator--() {
> - __ptr_ = static_cast<__node_pointer>(
> - __tree_prev(static_cast<__node_base_pointer>(__ptr_)));
> + __ptr_ =
> static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>(
> + static_cast<__end_node_pointer>(__ptr_)));
> return *this;
> }
>
> @@ -889,12 +940,19 @@ private:
> _LIBCPP_INLINE_VISIBILITY
> explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT
> : __ptr_(__p) {}
> + _LIBCPP_INLINE_VISIBILITY
> + explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT
> + : __ptr_(__p) {}
> + _LIBCPP_INLINE_VISIBILITY
> + __node_pointer __get_np() const { return
> static_cast<__node_pointer>(__ptr_); }
> +
> template <class, class, class> friend class __tree;
> template <class, class, class, class> friend class
> _LIBCPP_TYPE_VIS_ONLY map;
> template <class, class, class, class> friend class
> _LIBCPP_TYPE_VIS_ONLY multimap;
> template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set;
> template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY
> multiset;
> template <class> friend class _LIBCPP_TYPE_VIS_ONLY
> __map_const_iterator;
> +
> };
>
> template <class _Tp, class _Compare, class _Allocator>
> @@ -932,6 +990,9 @@ public:
> typedef typename _NodeTypes::__end_node_type __end_node_t;
> typedef typename _NodeTypes::__end_node_pointer __end_node_ptr;
>
> + typedef typename _NodeTypes::__parent_pointer __parent_pointer;
> + typedef typename _NodeTypes::__iter_pointer __iter_pointer;
> +
> typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type
> __node_allocator;
> typedef allocator_traits<__node_allocator> __node_traits;
>
> @@ -948,22 +1009,22 @@ private:
> "Allocator does not rebind pointers in a sane manner.");
>
> private:
> - __node_pointer __begin_node_;
> + __iter_pointer __begin_node_;
> __compressed_pair<__end_node_t, __node_allocator> __pair1_;
> __compressed_pair<size_type, value_compare> __pair3_;
>
> public:
> _LIBCPP_INLINE_VISIBILITY
> - __node_pointer __end_node() _NOEXCEPT
> + __iter_pointer __end_node() _NOEXCEPT
> {
> - return static_cast<__node_pointer>(
> + return static_cast<__iter_pointer>(
>
> pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
> );
> }
> _LIBCPP_INLINE_VISIBILITY
> - __node_pointer __end_node() const _NOEXCEPT
> + __iter_pointer __end_node() const _NOEXCEPT
> {
> - return static_cast<__node_pointer>(
> + return static_cast<__iter_pointer>(
> pointer_traits<__end_node_ptr>::pointer_to(
> const_cast<__end_node_t&>(__pair1_.first())
> )
> @@ -976,9 +1037,9 @@ private:
> const __node_allocator& __node_alloc() const _NOEXCEPT
> {return __pair1_.second();}
> _LIBCPP_INLINE_VISIBILITY
> - __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
> + __iter_pointer& __begin_node() _NOEXCEPT {return __begin_node_;}
> _LIBCPP_INLINE_VISIBILITY
> - const __node_pointer& __begin_node() const _NOEXCEPT {return
> __begin_node_;}
> + const __iter_pointer& __begin_node() const _NOEXCEPT {return
> __begin_node_;}
> public:
> _LIBCPP_INLINE_VISIBILITY
> allocator_type __alloc() const _NOEXCEPT
> @@ -1000,6 +1061,10 @@ public:
> __node_pointer __root() const _NOEXCEPT
> {return static_cast<__node_pointer>(__end_node()->__left_);}
>
> + __node_base_pointer* __root_ptr() const _NOEXCEPT {
> + return _VSTD::addressof(__end_node()->__left_);
> + }
> +
> typedef __tree_iterator<value_type, __node_pointer, difference_type>
> iterator;
> typedef __tree_const_iterator<value_type, __node_pointer,
> difference_type> const_iterator;
>
> @@ -1257,7 +1322,7 @@ public:
> template <class _Key>
> size_type __erase_multi(const _Key& __k);
>
> - void __insert_node_at(__node_base_pointer __parent,
> + void __insert_node_at(__parent_pointer __parent,
> __node_base_pointer& __child,
> __node_base_pointer __new_node);
>
> @@ -1278,7 +1343,7 @@ public:
> template <class _Key>
> iterator __lower_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result);
> + __iter_pointer __result);
> template <class _Key>
> _LIBCPP_INLINE_VISIBILITY
> const_iterator lower_bound(const _Key& __v) const
> @@ -1286,7 +1351,7 @@ public:
> template <class _Key>
> const_iterator __lower_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result) const;
> + __iter_pointer __result) const;
> template <class _Key>
> _LIBCPP_INLINE_VISIBILITY
> iterator upper_bound(const _Key& __v)
> @@ -1294,7 +1359,7 @@ public:
> template <class _Key>
> iterator __upper_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result);
> + __iter_pointer __result);
> template <class _Key>
> _LIBCPP_INLINE_VISIBILITY
> const_iterator upper_bound(const _Key& __v) const
> @@ -1302,7 +1367,7 @@ public:
> template <class _Key>
> const_iterator __upper_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result) const;
> + __iter_pointer __result) const;
> template <class _Key>
> pair<iterator, iterator>
> __equal_range_unique(const _Key& __k);
> @@ -1322,19 +1387,20 @@ public:
>
> __node_holder remove(const_iterator __p) _NOEXCEPT;
> private:
> - typename __node_base::pointer&
> - __find_leaf_low(typename __node_base::pointer& __parent, const
> key_type& __v);
> - typename __node_base::pointer&
> - __find_leaf_high(typename __node_base::pointer& __parent, const
> key_type& __v);
> - typename __node_base::pointer&
> + __node_base_pointer&
> + __find_leaf_low(__parent_pointer& __parent, const key_type& __v);
> + __node_base_pointer&
> + __find_leaf_high(__parent_pointer& __parent, const key_type& __v);
> + __node_base_pointer&
> __find_leaf(const_iterator __hint,
> - typename __node_base::pointer& __parent, const
> key_type& __v);
> + __parent_pointer& __parent, const key_type& __v);
> template <class _Key>
> - typename __node_base::pointer&
> - __find_equal(typename __node_base::pointer& __parent, const _Key&
> __v);
> + __node_base_pointer&
> + __find_equal(__parent_pointer& __parent, const _Key& __v);
> template <class _Key>
> - typename __node_base::pointer&
> - __find_equal(const_iterator __hint, typename
> __node_base::pointer& __parent,
> + __node_base_pointer&
> + __find_equal(const_iterator __hint, __parent_pointer& __parent,
> + __node_base_pointer& __dummy,
> const _Key& __v);
>
> #ifndef _LIBCPP_CXX03_LANG
> @@ -1396,7 +1462,7 @@ __tree<_Tp, _Compare, _Allocator>::__tre
>
> template <class _Tp, class _Compare, class _Allocator>
> __tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
> - : __begin_node_(__node_pointer()),
> + : __begin_node_(__iter_pointer()),
> __pair1_(__node_allocator(__a)),
> __pair3_(0)
> {
> @@ -1406,7 +1472,7 @@ __tree<_Tp, _Compare, _Allocator>::__tre
> template <class _Tp, class _Compare, class _Allocator>
> __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
> const allocator_type& __a)
> - : __begin_node_(__node_pointer()),
> + : __begin_node_(__iter_pointer()),
> __pair1_(__node_allocator(__a)),
> __pair3_(0, __comp)
> {
> @@ -1418,7 +1484,7 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
> __tree<_Tp, _Compare, _Allocator>::__detach()
> {
> - __node_pointer __cache = __begin_node();
> + __node_pointer __cache = static_cast<__node_pointer>(__begin_node());
> __begin_node() = __end_node();
> __end_node()->__left_->__parent_ = nullptr;
> __end_node()->__left_ = nullptr;
> @@ -1450,7 +1516,7 @@ __tree<_Tp, _Compare, _Allocator>::__det
> return
> static_cast<__node_pointer>(__tree_leaf(__cache->__right_));
> }
> // __cache is right child
> - __cache->__parent_->__right_ = nullptr;
> + __cache->__parent_unsafe()->__right_ = nullptr;
> __cache = static_cast<__node_pointer>(__cache->__parent_);
> if (__cache->__left_ == nullptr)
> return __cache;
> @@ -1563,7 +1629,7 @@ __tree<_Tp, _Compare, _Allocator>::__ass
>
> template <class _Tp, class _Compare, class _Allocator>
> __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
> - : __begin_node_(__node_pointer()),
> + : __begin_node_(__iter_pointer()),
>
> __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
> __pair3_(0, __t.value_comp())
> {
> @@ -1585,7 +1651,7 @@ __tree<_Tp, _Compare, _Allocator>::__tre
> __begin_node() = __end_node();
> else
> {
> - __end_node()->__left_->__parent_ =
> static_cast<__node_base_pointer>(__end_node());
> + __end_node()->__left_->__parent_ =
> static_cast<__parent_pointer>(__end_node());
> __t.__begin_node() = __t.__end_node();
> __t.__end_node()->__left_ = nullptr;
> __t.size() = 0;
> @@ -1605,7 +1671,7 @@ __tree<_Tp, _Compare, _Allocator>::__tre
> {
> __begin_node() = __t.__begin_node();
> __end_node()->__left_ = __t.__end_node()->__left_;
> - __end_node()->__left_->__parent_ =
> static_cast<__node_base_pointer>(__end_node());
> + __end_node()->__left_->__parent_ =
> static_cast<__parent_pointer>(__end_node());
> size() = __t.size();
> __t.__begin_node() = __t.__end_node();
> __t.__end_node()->__left_ = nullptr;
> @@ -1633,7 +1699,7 @@ __tree<_Tp, _Compare, _Allocator>::__mov
> __begin_node() = __end_node();
> else
> {
> - __end_node()->__left_->__parent_ =
> static_cast<__node_base_pointer>(__end_node());
> + __end_node()->__left_->__parent_ =
> static_cast<__parent_pointer>(__end_node());
> __t.__begin_node() = __t.__end_node();
> __t.__end_node()->__left_ = nullptr;
> __t.size() = 0;
> @@ -1743,11 +1809,11 @@ __tree<_Tp, _Compare, _Allocator>::swap(
> if (size() == 0)
> __begin_node() = __end_node();
> else
> - __end_node()->__left_->__parent_ =
> static_cast<__node_base_pointer>(__end_node());
> + __end_node()->__left_->__parent_ =
> static_cast<__parent_pointer>(__end_node());
> if (__t.size() == 0)
> __t.__begin_node() = __t.__end_node();
> else
> - __t.__end_node()->__left_->__parent_ =
> static_cast<__node_base_pointer>(__t.__end_node());
> + __t.__end_node()->__left_->__parent_ =
> static_cast<__parent_pointer>(__t.__end_node());
> }
>
> template <class _Tp, class _Compare, class _Allocator>
> @@ -1764,8 +1830,8 @@ __tree<_Tp, _Compare, _Allocator>::clear
> // Set __parent to parent of null leaf
> // Return reference to null leaf
> template <class _Tp, class _Compare, class _Allocator>
> -typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
> -__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename
> __node_base::pointer& __parent,
> +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
> +__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__parent_pointer&
> __parent,
> const key_type& __v)
> {
> __node_pointer __nd = __root();
> @@ -1779,8 +1845,8 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> __nd = static_cast<__node_pointer>(__nd->__right_);
> else
> {
> - __parent = static_cast<__node_base_pointer>(__nd);
> - return __parent->__right_;
> + __parent = static_cast<__parent_pointer>(__nd);
> + return __nd->__right_;
> }
> }
> else
> @@ -1789,13 +1855,13 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> __nd = static_cast<__node_pointer>(__nd->__left_);
> else
> {
> - __parent = static_cast<__node_base_pointer>(__nd);
> + __parent = static_cast<__parent_pointer>(__nd);
> return __parent->__left_;
> }
> }
> }
> }
> - __parent = static_cast<__node_base_pointer>(__end_node());
> + __parent = static_cast<__parent_pointer>(__end_node());
> return __parent->__left_;
> }
>
> @@ -1803,8 +1869,8 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // Set __parent to parent of null leaf
> // Return reference to null leaf
> template <class _Tp, class _Compare, class _Allocator>
> -typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
> -__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename
> __node_base::pointer& __parent,
> +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
> +__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__parent_pointer&
> __parent,
> const key_type& __v)
> {
> __node_pointer __nd = __root();
> @@ -1818,7 +1884,7 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> __nd = static_cast<__node_pointer>(__nd->__left_);
> else
> {
> - __parent = static_cast<__node_base_pointer>(__nd);
> + __parent = static_cast<__parent_pointer>(__nd);
> return __parent->__left_;
> }
> }
> @@ -1828,13 +1894,13 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> __nd = static_cast<__node_pointer>(__nd->__right_);
> else
> {
> - __parent = static_cast<__node_base_pointer>(__nd);
> - return __parent->__right_;
> + __parent = static_cast<__parent_pointer>(__nd);
> + return __nd->__right_;
> }
> }
> }
> }
> - __parent = static_cast<__node_base_pointer>(__end_node());
> + __parent = static_cast<__parent_pointer>(__end_node());
> return __parent->__left_;
> }
>
> @@ -1845,9 +1911,9 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // Set __parent to parent of null leaf
> // Return reference to null leaf
> template <class _Tp, class _Compare, class _Allocator>
> -typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
> +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
> __tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint,
> - typename
> __node_base::pointer& __parent,
> + __parent_pointer& __parent,
> const key_type& __v)
> {
> if (__hint == end() || !value_comp()(*__hint, __v)) // check before
> @@ -1859,13 +1925,13 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // *prev(__hint) <= __v <= *__hint
> if (__hint.__ptr_->__left_ == nullptr)
> {
> - __parent =
> static_cast<__node_base_pointer>(__hint.__ptr_);
> + __parent = static_cast<__parent_pointer>(__hint.__ptr_);
> return __parent->__left_;
> }
> else
> {
> - __parent =
> static_cast<__node_base_pointer>(__prior.__ptr_);
> - return __parent->__right_;
> + __parent = static_cast<__parent_pointer>(__prior.__ptr_);
> + return
> static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
> }
> }
> // __v < *prev(__hint)
> @@ -1881,43 +1947,44 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // If __v exists, set parent to node of __v and return reference to node
> of __v
> template <class _Tp, class _Compare, class _Allocator>
> template <class _Key>
> -typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
> -__tree<_Tp, _Compare, _Allocator>::__find_equal(typename
> __node_base::pointer& __parent,
> +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
> +__tree<_Tp, _Compare, _Allocator>::__find_equal(__parent_pointer&
> __parent,
> const _Key& __v)
> {
> __node_pointer __nd = __root();
> + __node_base_pointer* __nd_ptr = __root_ptr();
> if (__nd != nullptr)
> {
> while (true)
> {
> if (value_comp()(__v, __nd->__value_))
> {
> - if (__nd->__left_ != nullptr)
> + if (__nd->__left_ != nullptr) {
> + __nd_ptr = _VSTD::addressof(__nd->__left_);
> __nd = static_cast<__node_pointer>(__nd->__left_);
> - else
> - {
> - __parent = static_cast<__node_base_pointer>(__nd);
> + } else {
> + __parent = static_cast<__parent_pointer>(__nd);
> return __parent->__left_;
> }
> }
> else if (value_comp()(__nd->__value_, __v))
> {
> - if (__nd->__right_ != nullptr)
> + if (__nd->__right_ != nullptr) {
> + __nd_ptr = _VSTD::addressof(__nd->__right_);
> __nd = static_cast<__node_pointer>(__nd->__right_);
> - else
> - {
> - __parent = static_cast<__node_base_pointer>(__nd);
> - return __parent->__right_;
> + } else {
> + __parent = static_cast<__parent_pointer>(__nd);
> + return __nd->__right_;
> }
> }
> else
> {
> - __parent = static_cast<__node_base_pointer>(__nd);
> - return __parent;
> + __parent = static_cast<__parent_pointer>(__nd);
> + return *__nd_ptr;
> }
> }
> }
> - __parent = static_cast<__node_base_pointer>(__end_node());
> + __parent = static_cast<__parent_pointer>(__end_node());
> return __parent->__left_;
> }
>
> @@ -1930,9 +1997,10 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // If __v exists, set parent to node of __v and return reference to node
> of __v
> template <class _Tp, class _Compare, class _Allocator>
> template <class _Key>
> -typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer&
> +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
> __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
> - typename
> __node_base::pointer& __parent,
> + __parent_pointer&
> __parent,
> + __node_base_pointer&
> __dummy,
> const _Key& __v)
> {
> if (__hint == end() || value_comp()(__v, *__hint)) // check before
> @@ -1944,13 +2012,13 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> // *prev(__hint) < __v < *__hint
> if (__hint.__ptr_->__left_ == nullptr)
> {
> - __parent =
> static_cast<__node_base_pointer>(__hint.__ptr_);
> + __parent = static_cast<__parent_pointer>(__hint.__ptr_);
> return __parent->__left_;
> }
> else
> {
> - __parent =
> static_cast<__node_base_pointer>(__prior.__ptr_);
> - return __parent->__right_;
> + __parent = static_cast<__parent_pointer>(__prior.__ptr_);
> + return
> static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
> }
> }
> // __v <= *prev(__hint)
> @@ -1963,14 +2031,14 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> if (__next == end() || value_comp()(__v, *__next))
> {
> // *__hint < __v < *_VSTD::next(__hint)
> - if (__hint.__ptr_->__right_ == nullptr)
> + if (__hint.__get_np()->__right_ == nullptr)
> {
> - __parent =
> static_cast<__node_base_pointer>(__hint.__ptr_);
> - return __parent->__right_;
> + __parent = static_cast<__parent_pointer>(__hint.__ptr_);
> + return
> static_cast<__node_base_pointer>(__hint.__ptr_)->__right_;
> }
> else
> {
> - __parent =
> static_cast<__node_base_pointer>(__next.__ptr_);
> + __parent = static_cast<__parent_pointer>(__next.__ptr_);
> return __parent->__left_;
> }
> }
> @@ -1978,15 +2046,16 @@ __tree<_Tp, _Compare, _Allocator>::__fin
> return __find_equal(__parent, __v);
> }
> // else __v == *__hint
> - __parent = static_cast<__node_base_pointer>(__hint.__ptr_);
> - return __parent;
> + __parent = static_cast<__parent_pointer>(__hint.__ptr_);
> + __dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
> + return __dummy;
> }
>
> template <class _Tp, class _Compare, class _Allocator>
> void
> -__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer
> __parent,
> +__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__parent_pointer
> __parent,
> __node_base_pointer&
> __child,
> - __node_base_pointer
> __new_node)
> + __node_base_pointer
> __new_node)
> {
> __new_node->__left_ = nullptr;
> __new_node->__right_ = nullptr;
> @@ -1994,7 +2063,7 @@ __tree<_Tp, _Compare, _Allocator>::__ins
> // __new_node->__is_black_ is initialized in
> __tree_balance_after_insert
> __child = __new_node;
> if (__begin_node()->__left_ != nullptr)
> - __begin_node() =
> static_cast<__node_pointer>(__begin_node()->__left_);
> + __begin_node() =
> static_cast<__iter_pointer>(__begin_node()->__left_);
> __tree_balance_after_insert(__end_node()->__left_, __child);
> ++size();
> }
> @@ -2011,7 +2080,7 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const&
> __k, _Args& __args)
> #endif
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_equal(__parent, __k);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> bool __inserted = false;
> @@ -2044,8 +2113,9 @@ __tree<_Tp, _Compare, _Allocator>::__emp
> const_iterator __p, _Key const& __k, _Args& __args)
> #endif
> {
> - __node_base_pointer __parent;
> - __node_base_pointer& __child = __find_equal(__p, __parent, __k);
> + __parent_pointer __parent;
> + __node_base_pointer __dummy;
> + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy,
> __k);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> if (__child == nullptr)
> {
> @@ -2084,7 +2154,7 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&...
> __args)
> {
> __node_holder __h =
> __construct_node(_VSTD::forward<_Args>(__args)...);
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_equal(__parent, __h->__value_);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> bool __inserted = false;
> @@ -2103,8 +2173,9 @@ typename __tree<_Tp, _Compare, _Allocato
> __tree<_Tp, _Compare,
> _Allocator>::__emplace_hint_unique_impl(const_iterator __p, _Args&&...
> __args)
> {
> __node_holder __h =
> __construct_node(_VSTD::forward<_Args>(__args)...);
> - __node_base_pointer __parent;
> - __node_base_pointer& __child = __find_equal(__p, __parent,
> __h->__value_);
> + __parent_pointer __parent;
> + __node_base_pointer __dummy;
> + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy,
> __h->__value_);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> if (__child == nullptr)
> {
> @@ -2120,7 +2191,7 @@ typename __tree<_Tp, _Compare, _Allocato
> __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args)
> {
> __node_holder __h =
> __construct_node(_VSTD::forward<_Args>(__args)...);
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf_high(__parent,
> _NodeTypes::__get_key(__h->__value_));
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__h.get()));
> return iterator(static_cast<__node_pointer>(__h.release()));
> @@ -2133,7 +2204,7 @@ __tree<_Tp, _Compare, _Allocator>::__emp
> _Args&&... __args)
> {
> __node_holder __h =
> __construct_node(_VSTD::forward<_Args>(__args)...);
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf(__p, __parent,
> _NodeTypes::__get_key(__h->__value_));
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__h.get()));
> return iterator(static_cast<__node_pointer>(__h.release()));
> @@ -2160,7 +2231,7 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::__insert_multi(const
> __container_value_type& __v)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf_high(__parent,
> _NodeTypes::__get_key(__v));
> __node_holder __h = __construct_node(__v);
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__h.get()));
> @@ -2171,7 +2242,7 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p,
> const __container_value_type& __v)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf(__p, __parent,
> _NodeTypes::__get_key(__v));
> __node_holder __h = __construct_node(__v);
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__h.get()));
> @@ -2183,7 +2254,7 @@ template <class _Tp, class _Compare, cla
> pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
> __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer
> __nd)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> bool __inserted = false;
> @@ -2201,7 +2272,8 @@ typename __tree<_Tp, _Compare, _Allocato
> __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator
> __p,
> __node_pointer
> __nd)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> + __node_base_pointer __dummy;
> __node_base_pointer& __child = __find_equal(__p, __parent,
> __nd->__value_);
> __node_pointer __r = static_cast<__node_pointer>(__child);
> if (__child == nullptr)
> @@ -2216,7 +2288,7 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer
> __nd)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf_high(__parent,
> _NodeTypes::__get_key(__nd->__value_));
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__nd));
> return iterator(__nd);
> @@ -2227,7 +2299,7 @@ typename __tree<_Tp, _Compare, _Allocato
> __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
> __node_pointer
> __nd)
> {
> - __node_base_pointer __parent;
> + __parent_pointer __parent;
> __node_base_pointer& __child = __find_leaf(__p, __parent,
> _NodeTypes::__get_key(__nd->__value_));
> __insert_node_at(__parent, __child,
> static_cast<__node_base_pointer>(__nd));
> return iterator(__nd);
> @@ -2237,10 +2309,10 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
> {
> - __node_pointer __np = __p.__ptr_;
> - iterator __r(__np);
> + __node_pointer __np = __p.__get_np();
> + iterator __r(__p.__ptr_);
> ++__r;
> - if (__begin_node() == __np)
> + if (__begin_node() == __p.__ptr_)
> __begin_node() = __r.__ptr_;
> --size();
> __node_allocator& __na = __node_alloc();
> @@ -2312,13 +2384,11 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::size_type
> __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const
> {
> - __node_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> @@ -2334,20 +2404,20 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::size_type
> __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const
> {
> - __node_pointer __result = __end_node();
> + __iter_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> + __result = static_cast<__iter_pointer>(__rt);
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> __rt = static_cast<__node_pointer>(__rt->__right_);
> else
> return _VSTD::distance(
> - __lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_), __rt),
> + __lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_),
> static_cast<__iter_pointer>(__rt)),
> __upper_bound(__k,
> static_cast<__node_pointer>(__rt->__right_), __result)
> );
> }
> @@ -2359,13 +2429,13 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result)
> + __iter_pointer __result)
> {
> while (__root != nullptr)
> {
> if (!value_comp()(__root->__value_, __v))
> {
> - __result = __root;
> + __result = static_cast<__iter_pointer>(__root);
> __root = static_cast<__node_pointer>(__root->__left_);
> }
> else
> @@ -2379,13 +2449,13 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::const_iterator
> __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result)
> const
> + __iter_pointer __result)
> const
> {
> while (__root != nullptr)
> {
> if (!value_comp()(__root->__value_, __v))
> {
> - __result = __root;
> + __result = static_cast<__iter_pointer>(__root);
> __root = static_cast<__node_pointer>(__root->__left_);
> }
> else
> @@ -2399,13 +2469,13 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::iterator
> __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result)
> + __iter_pointer __result)
> {
> while (__root != nullptr)
> {
> if (value_comp()(__v, __root->__value_))
> {
> - __result = __root;
> + __result = static_cast<__iter_pointer>(__root);
> __root = static_cast<__node_pointer>(__root->__left_);
> }
> else
> @@ -2419,13 +2489,13 @@ template <class _Key>
> typename __tree<_Tp, _Compare, _Allocator>::const_iterator
> __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v,
> __node_pointer __root,
> - __node_pointer __result)
> const
> + __iter_pointer __result)
> const
> {
> while (__root != nullptr)
> {
> if (value_comp()(__v, __root->__value_))
> {
> - __result = __root;
> + __result = static_cast<__iter_pointer>(__root);
> __root = static_cast<__node_pointer>(__root->__left_);
> }
> else
> @@ -2441,13 +2511,13 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
> {
> typedef pair<iterator, iterator> _Pp;
> - __node_pointer __result = __end_node();
> + __iter_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> + __result = static_cast<__iter_pointer>(__rt);
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> @@ -2456,7 +2526,7 @@ __tree<_Tp, _Compare, _Allocator>::__equ
> return _Pp(iterator(__rt),
> iterator(
> __rt->__right_ != nullptr ?
> -
> static_cast<__node_pointer>(__tree_min(__rt->__right_))
> +
> static_cast<__iter_pointer>(__tree_min(__rt->__right_))
> : __result));
> }
> return _Pp(iterator(__result), iterator(__result));
> @@ -2469,13 +2539,13 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k)
> const
> {
> typedef pair<const_iterator, const_iterator> _Pp;
> - __node_pointer __result = __end_node();
> + __iter_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> + __result = static_cast<__iter_pointer>(__rt);
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> @@ -2484,7 +2554,7 @@ __tree<_Tp, _Compare, _Allocator>::__equ
> return _Pp(const_iterator(__rt),
> const_iterator(
> __rt->__right_ != nullptr ?
> -
> static_cast<__node_pointer>(__tree_min(__rt->__right_))
> +
> static_cast<__iter_pointer>(__tree_min(__rt->__right_))
> : __result));
> }
> return _Pp(const_iterator(__result), const_iterator(__result));
> @@ -2497,19 +2567,19 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
> {
> typedef pair<iterator, iterator> _Pp;
> - __node_pointer __result = __end_node();
> + __iter_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> + __result = static_cast<__iter_pointer>(__rt);
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> __rt = static_cast<__node_pointer>(__rt->__right_);
> else
> - return _Pp(__lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_), __rt),
> + return _Pp(__lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_),
> static_cast<__iter_pointer>(__rt)),
> __upper_bound(__k,
> static_cast<__node_pointer>(__rt->__right_), __result));
> }
> return _Pp(iterator(__result), iterator(__result));
> @@ -2522,19 +2592,19 @@ pair<typename __tree<_Tp, _Compare, _All
> __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k)
> const
> {
> typedef pair<const_iterator, const_iterator> _Pp;
> - __node_pointer __result = __end_node();
> + __iter_pointer __result = __end_node();
> __node_pointer __rt = __root();
> while (__rt != nullptr)
> {
> if (value_comp()(__k, __rt->__value_))
> {
> - __result = __rt;
> + __result = static_cast<__iter_pointer>(__rt);
> __rt = static_cast<__node_pointer>(__rt->__left_);
> }
> else if (value_comp()(__rt->__value_, __k))
> __rt = static_cast<__node_pointer>(__rt->__right_);
> else
> - return _Pp(__lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_), __rt),
> + return _Pp(__lower_bound(__k,
> static_cast<__node_pointer>(__rt->__left_),
> static_cast<__iter_pointer>(__rt)),
> __upper_bound(__k,
> static_cast<__node_pointer>(__rt->__right_), __result));
> }
> return _Pp(const_iterator(__result), const_iterator(__result));
> @@ -2544,13 +2614,13 @@ template <class _Tp, class _Compare, cla
> typename __tree<_Tp, _Compare, _Allocator>::__node_holder
> __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT
> {
> - __node_pointer __np = __p.__ptr_;
> - if (__begin_node() == __np)
> + __node_pointer __np = __p.__get_np();
> + if (__begin_node() == __p.__ptr_)
> {
> if (__np->__right_ != nullptr)
> - __begin_node() = static_cast<__node_pointer>(__np->__right_);
> + __begin_node() = static_cast<__iter_pointer>(__np->__right_);
> else
> - __begin_node() = static_cast<__node_pointer>(__np->__parent_);
> + __begin_node() = static_cast<__iter_pointer>(__np->__parent_);
> }
> --size();
> __tree_remove(__end_node()->__left_,
>
> Modified:
> libcxx/trunk/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> ---
> libcxx/trunk/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp
> (original)
> +++
> libcxx/trunk/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp
> Tue Jul 19 12:56:20 2016
> @@ -24,6 +24,9 @@ struct Node
> Node* __parent_;
> bool __is_black_;
>
> + Node* __parent_unsafe() const { return __parent_; }
> + void __set_parent(Node* x) { __parent_ = x;}
> +
> Node() : __left_(), __right_(), __parent_(), __is_black_() {}
> };
>
>
> Modified:
> libcxx/trunk/test/libcxx/containers/associative/tree_left_rotate.pass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/associative/tree_left_rotate.pass.cpp?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> ---
> libcxx/trunk/test/libcxx/containers/associative/tree_left_rotate.pass.cpp
> (original)
> +++
> libcxx/trunk/test/libcxx/containers/associative/tree_left_rotate.pass.cpp
> Tue Jul 19 12:56:20 2016
> @@ -23,6 +23,9 @@ struct Node
> Node* __right_;
> Node* __parent_;
>
> + Node* __parent_unsafe() const { return __parent_; }
> + void __set_parent(Node* x) { __parent_ = x;}
> +
> Node() : __left_(), __right_(), __parent_() {}
> };
>
>
> Modified:
> libcxx/trunk/test/libcxx/containers/associative/tree_remove.pass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/associative/tree_remove.pass.cpp?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> --- libcxx/trunk/test/libcxx/containers/associative/tree_remove.pass.cpp
> (original)
> +++ libcxx/trunk/test/libcxx/containers/associative/tree_remove.pass.cpp
> Tue Jul 19 12:56:20 2016
> @@ -24,6 +24,9 @@ struct Node
> Node* __parent_;
> bool __is_black_;
>
> + Node* __parent_unsafe() const { return __parent_; }
> + void __set_parent(Node* x) { __parent_ = x;}
> +
> Node() : __left_(), __right_(), __parent_(), __is_black_() {}
> };
>
>
> Modified:
> libcxx/trunk/test/libcxx/containers/associative/tree_right_rotate.pass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/containers/associative/tree_right_rotate.pass.cpp?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> ---
> libcxx/trunk/test/libcxx/containers/associative/tree_right_rotate.pass.cpp
> (original)
> +++
> libcxx/trunk/test/libcxx/containers/associative/tree_right_rotate.pass.cpp
> Tue Jul 19 12:56:20 2016
> @@ -23,6 +23,9 @@ struct Node
> Node* __right_;
> Node* __parent_;
>
> + Node* __parent_unsafe() const { return __parent_; }
> + void __set_parent(Node* x) { __parent_ = x;}
> +
> Node() : __left_(), __right_(), __parent_() {}
> };
>
>
> Added:
> libcxx/trunk/test/std/containers/associative/map/PR28469_undefined_behavior_segfault.sh.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/map/PR28469_undefined_behavior_segfault.sh.cpp?rev=276003&view=auto
>
> ==============================================================================
> ---
> libcxx/trunk/test/std/containers/associative/map/PR28469_undefined_behavior_segfault.sh.cpp
> (added)
> +++
> libcxx/trunk/test/std/containers/associative/map/PR28469_undefined_behavior_segfault.sh.cpp
> Tue Jul 19 12:56:20 2016
> @@ -0,0 +1,31 @@
>
> +//===----------------------------------------------------------------------===//
> +//
> +// 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.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +// RUN: %build -O2
> +// RUN: %run
> +
> +// <map>
> +
> +// Previously this code caused a segfault when compiled at -O2 due to
> undefined
> +// behavior in __tree. See https://llvm.org/bugs/show_bug.cgi?id=28469
> +
> +#include <functional>
> +#include <map>
> +
> +void dummy() {}
> +
> +struct F {
> + std::map<int, std::function<void()> > m;
> + F() { m[42] = &dummy; }
> +};
> +
> +int main() {
> + F f;
> + f = F();
> +}
>
> Modified: libcxx/trunk/test/ubsan_blacklist.txt
> URL:
> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/ubsan_blacklist.txt?rev=276003&r1=276002&r2=276003&view=diff
>
> ==============================================================================
> --- libcxx/trunk/test/ubsan_blacklist.txt (original)
> +++ libcxx/trunk/test/ubsan_blacklist.txt Tue Jul 19 12:56:20 2016
> @@ -1,2 +1 @@
> -fun:*__tree*
> fun:*__hash_table*
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160719/e1c19af6/attachment-0001.html>
More information about the cfe-commits
mailing list