[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