[libcxx] r276003 - Fix undefined behavior in __tree

Marshall Clow via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 19 22:42:51 PDT 2016


On Tue, Jul 19, 2016 at 11:06 AM, Eric Fiselier <eric at efcs.ca> wrote:

> @Hans. This needs to be merged into 3.9. It fixes PR28469 which is a
> release blocker.
>

I'm fine with this.

-- Marshall


>
> 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/209d006a/attachment-0001.html>


More information about the cfe-commits mailing list