[libcxx-commits] [libcxx] [libc++] Require fancy pointer to be correctly convertible (PR #152989)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 11 03:21:09 PDT 2025


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/152989

This patch removes a bunch of code that works around incorrect implementations of fancy pointers. It's possible that this breaks user code. However, any breakage is likely to catch serious latent bugs.


>From 19c6b7d52baa9cd07338f1a5351304dc92e0b665 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 11 Aug 2025 12:19:39 +0200
Subject: [PATCH] [libc++] Require fancy pointer to be correctly convertible

---
 libcxx/include/__hash_table              |  10 +-
 libcxx/include/__memory/pointer_traits.h |  12 --
 libcxx/include/__tree                    | 145 +++++++++++------------
 libcxx/include/forward_list              |  38 +++---
 libcxx/test/support/min_allocator.h      |   7 ++
 5 files changed, 98 insertions(+), 114 deletions(-)

diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index dacc152030e14..dbc41fdf0f459 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -96,7 +96,7 @@ struct __hash_node_base {
   __next_pointer __next_;
 
   _LIBCPP_HIDE_FROM_ABI __next_pointer __ptr() _NOEXCEPT {
-    return static_cast<__next_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
+    return pointer_traits<__node_base_pointer>::pointer_to(*this);
   }
 
   _LIBCPP_HIDE_FROM_ABI __node_pointer __upcast() _NOEXCEPT {
@@ -1499,9 +1499,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p
     while (__pp->__next_ != __np)
       __pp = __pp->__next_;
     __cp->__next_ = __np;
-    __pp->__next_ = static_cast<__next_pointer>(__cp);
+    __pp->__next_ = __cp;
     ++size();
-    return iterator(static_cast<__next_pointer>(__cp));
+    return iterator(__cp);
   }
   return __node_insert_multi(__cp);
 }
@@ -1547,9 +1547,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const&
         __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
     } else {
       __h->__next_  = __pn->__next_;
-      __pn->__next_ = static_cast<__next_pointer>(__h.get());
+      __pn->__next_ = __h.get();
     }
-    __nd = static_cast<__next_pointer>(__h.release());
+    __nd = __h.release();
     // increment size
     ++size();
     __inserted = true;
diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index 8c7f8dff1b76b..336422befb6ee 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -252,18 +252,6 @@ concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p
 
 #endif
 
-// This function ensures safe conversions between fancy pointers at compile-time, where we avoid casts from/to
-// `__void_pointer` by obtaining the underlying raw pointer from the fancy pointer using `std::to_address`,
-// then dereferencing it to retrieve the pointed-to object, and finally constructing the target fancy pointer
-// to that object using the `std::pointer_traits<>::pinter_to` function.
-template <class _PtrTo, class _PtrFrom>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) {
-  using __ptr_traits   = pointer_traits<_PtrTo>;
-  using __element_type = typename __ptr_traits::element_type;
-  return __p ? __ptr_traits::pointer_to(*static_cast<__element_type*>(std::addressof(*__p)))
-             : static_cast<_PtrTo>(nullptr);
-}
-
 _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 6dadd0915c984..b804a542bbd8d 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -171,10 +171,10 @@ template <class _EndNodePtr, class _NodePtr>
 inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   if (__x->__right_ != nullptr)
-    return static_cast<_EndNodePtr>(std::__tree_min(__x->__right_));
+    return std::__tree_min(__x->__right_);
   while (!std::__tree_is_left_child(__x))
     __x = __x->__parent_unsafe();
-  return static_cast<_EndNodePtr>(__x->__parent_);
+  return __x->__parent_;
 }
 
 // Returns:  pointer to the previous in-order node before __x.
@@ -541,7 +541,7 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI pointer __parent_unsafe() const { return static_cast<pointer>(__parent_); }
 
-  _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); }
+  _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = __p; }
 
   ~__tree_node_base()                                  = delete;
   __tree_node_base(__tree_node_base const&)            = delete;
@@ -635,7 +635,7 @@ public:
   }
 
   _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator--() {
-    __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_));
+    __ptr_ = std::__tree_prev_iter<__node_base_pointer>(__ptr_);
     return *this;
   }
   _LIBCPP_HIDE_FROM_ABI __tree_iterator operator--(int) {
@@ -698,7 +698,7 @@ public:
   }
 
   _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator--() {
-    __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_));
+    __ptr_ = std::__tree_prev_iter<__node_base_pointer>(__ptr_);
     return *this;
   }
 
@@ -1212,12 +1212,12 @@ private:
     __node_pointer __new_node_ptr = __new_node.release();
 
     __new_node_ptr->__is_black_ = __src->__is_black_;
-    __new_node_ptr->__left_     = static_cast<__node_base_pointer>(__left.release());
-    __new_node_ptr->__right_    = static_cast<__node_base_pointer>(__right);
+    __new_node_ptr->__left_     = __left.release();
+    __new_node_ptr->__right_    = __right;
     if (__new_node_ptr->__left_)
-      __new_node_ptr->__left_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr);
+      __new_node_ptr->__left_->__parent_ = __new_node_ptr;
     if (__new_node_ptr->__right_)
-      __new_node_ptr->__right_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr);
+      __new_node_ptr->__right_->__parent_ = __new_node_ptr;
     return __new_node_ptr;
   }
 
@@ -1239,24 +1239,24 @@ private:
 
     // If we already have a left node in the destination tree, reuse it and copy-assign recursively
     if (__dest->__left_) {
-      __dest->__left_ = static_cast<__node_base_pointer>(__copy_assign_tree(
-          static_cast<__node_pointer>(__dest->__left_), static_cast<__node_pointer>(__src->__left_)));
+      __dest->__left_ =
+          __copy_assign_tree(static_cast<__node_pointer>(__dest->__left_), static_cast<__node_pointer>(__src->__left_));
 
       // Otherwise, we must create new nodes; copy-construct from here on
     } else if (__src->__left_) {
       auto __new_left       = __copy_construct_tree(static_cast<__node_pointer>(__src->__left_));
-      __dest->__left_       = static_cast<__node_base_pointer>(__new_left);
-      __new_left->__parent_ = static_cast<__end_node_pointer>(__dest);
+      __dest->__left_       = __new_left;
+      __new_left->__parent_ = __dest;
     }
 
     // Identical to the left case above, just for the right nodes
     if (__dest->__right_) {
-      __dest->__right_ = static_cast<__node_base_pointer>(__copy_assign_tree(
-          static_cast<__node_pointer>(__dest->__right_), static_cast<__node_pointer>(__src->__right_)));
+      __dest->__right_ = __copy_assign_tree(
+          static_cast<__node_pointer>(__dest->__right_), static_cast<__node_pointer>(__src->__right_));
     } else if (__src->__right_) {
       auto __new_right       = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_));
-      __dest->__right_       = static_cast<__node_base_pointer>(__new_right);
-      __new_right->__parent_ = static_cast<__end_node_pointer>(__dest);
+      __dest->__right_       = __new_right;
+      __new_right->__parent_ = __dest;
     }
 
     return __dest;
@@ -1332,15 +1332,14 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(
   __copy_assign_alloc(__t);
 
   if (__size_ != 0) {
-    *__root_ptr() = static_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root()));
+    *__root_ptr() = __copy_assign_tree(__root(), __t.__root());
   } else {
-    *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root()));
+    *__root_ptr() = __copy_construct_tree(__t.__root());
     if (__root())
       __root()->__parent_ = __end_node();
   }
-  __begin_node_ =
-      __end_node()->__left_ ? static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)) : __end_node();
-  __size_ = __t.size();
+  __begin_node_ = __end_node()->__left_ ? std::__tree_min(__end_node()->__left_) : __end_node();
+  __size_       = __t.size();
 
   return *this;
 }
@@ -1394,9 +1393,9 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
   if (__t.size() == 0)
     return;
 
-  *__root_ptr()       = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root()));
+  *__root_ptr()       = __copy_construct_tree(__t.__root());
   __root()->__parent_ = __end_node();
-  __begin_node_       = static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_));
+  __begin_node_       = std::__tree_min(__end_node()->__left_);
   __size_             = __t.size();
 }
 
@@ -1411,7 +1410,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_(
   if (__size_ == 0)
     __begin_node_ = __end_node();
   else {
-    __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node());
+    __end_node()->__left_->__parent_ = __end_node();
     __t.__begin_node_                = __t.__end_node();
     __t.__end_node()->__left_        = nullptr;
     __t.__size_                      = 0;
@@ -1427,7 +1426,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __
     else {
       __begin_node_                    = __t.__begin_node_;
       __end_node()->__left_            = __t.__end_node()->__left_;
-      __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node());
+      __end_node()->__left_->__parent_ = __end_node();
       __size_                          = __t.__size_;
       __t.__begin_node_                = __t.__end_node();
       __t.__end_node()->__left_        = nullptr;
@@ -1450,7 +1449,7 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
   if (__size_ == 0)
     __begin_node_ = __end_node();
   else {
-    __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node());
+    __end_node()->__left_->__parent_ = __end_node();
     __t.__begin_node_                = __t.__end_node();
     __t.__end_node()->__left_        = nullptr;
     __t.__size_                      = 0;
@@ -1545,14 +1544,14 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent,
         if (__nd->__right_ != nullptr)
           __nd = static_cast<__node_pointer>(__nd->__right_);
         else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __nd->__right_;
         }
       } else {
         if (__nd->__left_ != nullptr)
           __nd = static_cast<__node_pointer>(__nd->__left_);
         else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __parent->__left_;
         }
       }
@@ -1575,14 +1574,14 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent
         if (__nd->__left_ != nullptr)
           __nd = static_cast<__node_pointer>(__nd->__left_);
         else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __parent->__left_;
         }
       } else {
         if (__nd->__right_ != nullptr)
           __nd = static_cast<__node_pointer>(__nd->__right_);
         else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __nd->__right_;
         }
       }
@@ -1608,10 +1607,10 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co
     if (__prior == begin() || !value_comp()(__v, *--__prior)) {
       // *prev(__hint) <= __v <= *__hint
       if (__hint.__ptr_->__left_ == nullptr) {
-        __parent = static_cast<__end_node_pointer>(__hint.__ptr_);
+        __parent = __hint.__ptr_;
         return __parent->__left_;
       } else {
-        __parent = static_cast<__end_node_pointer>(__prior.__ptr_);
+        __parent = __prior.__ptr_;
         return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
       }
     }
@@ -1639,7 +1638,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co
           __nd_ptr = std::addressof(__nd->__left_);
           __nd     = static_cast<__node_pointer>(__nd->__left_);
         } else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __parent->__left_;
         }
       } else if (value_comp()(__nd->__value_, __v)) {
@@ -1647,11 +1646,11 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co
           __nd_ptr = std::addressof(__nd->__right_);
           __nd     = static_cast<__node_pointer>(__nd->__right_);
         } else {
-          __parent = static_cast<__end_node_pointer>(__nd);
+          __parent = __nd;
           return __nd->__right_;
         }
       } else {
-        __parent = static_cast<__end_node_pointer>(__nd);
+        __parent = __nd;
         return *__nd_ptr;
       }
     }
@@ -1719,7 +1718,7 @@ void __tree<_Tp, _Compare, _Allocator>::__insert_node_at(
   // __new_node->__is_black_ is initialized in __tree_balance_after_insert
   __child = __new_node;
   if (__begin_node_->__left_ != nullptr)
-    __begin_node_ = static_cast<__end_node_pointer>(__begin_node_->__left_);
+    __begin_node_ = __begin_node_->__left_;
   std::__tree_balance_after_insert(__end_node()->__left_, __child);
   ++__size_;
 }
@@ -1734,7 +1733,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _A
   bool __inserted              = false;
   if (__child == nullptr) {
     __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+    __insert_node_at(__parent, __child, __h.get());
     __r        = __h.release();
     __inserted = true;
   }
@@ -1753,7 +1752,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
   bool __inserted              = false;
   if (__child == nullptr) {
     __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+    __insert_node_at(__parent, __child, __h.get());
     __r        = __h.release();
     __inserted = true;
   }
@@ -1781,7 +1780,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) {
   __node_pointer __r           = static_cast<__node_pointer>(__child);
   bool __inserted              = false;
   if (__child == nullptr) {
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+    __insert_node_at(__parent, __child, __h.get());
     __r        = __h.release();
     __inserted = true;
   }
@@ -1798,7 +1797,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p
   __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_);
   __node_pointer __r           = static_cast<__node_pointer>(__child);
   if (__child == nullptr) {
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
+    __insert_node_at(__parent, __child, __h.get());
     __r = __h.release();
   }
   return iterator(__r);
@@ -1811,8 +1810,8 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) {
   __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-  return iterator(static_cast<__node_pointer>(__h.release()));
+  __insert_node_at(__parent, __child, __h.get());
+  return iterator(__h.release());
 }
 
 template <class _Tp, class _Compare, class _Allocator>
@@ -1822,8 +1821,8 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Arg
   __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
-  return iterator(static_cast<__node_pointer>(__h.release()));
+  __insert_node_at(__parent, __child, __h.get());
+  return iterator(__h.release());
 }
 
 template <class _Tp, class _Compare, class _Allocator>
@@ -1835,7 +1834,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _
   bool __inserted              = false;
   if (__child == nullptr) {
     __assign_value(__nd->__value_, __v);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
+    __insert_node_at(__parent, __child, __nd);
     __r        = __nd;
     __inserted = true;
   }
@@ -1847,7 +1846,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator
 __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) {
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
+  __insert_node_at(__parent, __child, __nd);
   return iterator(__nd);
 }
 
@@ -1856,7 +1855,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator
 __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) {
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
+  __insert_node_at(__parent, __child, __nd);
   return iterator(__nd);
 }
 
@@ -1886,7 +1885,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n
   if (__child != nullptr)
     return _InsertReturnType{iterator(static_cast<__node_pointer>(__child)), false, std::move(__nh)};
 
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
+  __insert_node_at(__parent, __child, __ptr);
   __nh.__release_ptr();
   return _InsertReturnType{iterator(__ptr), true, _NodeHandle()};
 }
@@ -1904,7 +1903,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
   __node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, __ptr->__value_);
   __node_pointer __r           = static_cast<__node_pointer>(__child);
   if (__child == nullptr) {
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
+    __insert_node_at(__parent, __child, __ptr);
     __r = __ptr;
     __nh.__release_ptr();
   }
@@ -1941,7 +1940,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg
     if (__child != nullptr)
       continue;
     __source.__remove_node_pointer(__src_ptr);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__src_ptr));
+    __insert_node_at(__parent, __child, __src_ptr);
   }
 }
 
@@ -1954,7 +1953,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh
   __node_pointer __ptr = __nh.__ptr_;
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf_high(__parent, __ptr->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
+  __insert_node_at(__parent, __child, __ptr);
   __nh.__release_ptr();
   return iterator(__ptr);
 }
@@ -1969,7 +1968,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(const_iterator __h
   __node_pointer __ptr = __nh.__ptr_;
   __end_node_pointer __parent;
   __node_base_pointer& __child = __find_leaf(__hint, __parent, __ptr->__value_);
-  __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
+  __insert_node_at(__parent, __child, __ptr);
   __nh.__release_ptr();
   return iterator(__ptr);
 }
@@ -1985,7 +1984,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg
     __node_base_pointer& __child = __find_leaf_high(__parent, __src_ptr->__value_);
     ++__i;
     __source.__remove_node_pointer(__src_ptr);
-    __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__src_ptr));
+    __insert_node_at(__parent, __child, __src_ptr);
   }
 }
 
@@ -2074,13 +2073,13 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const {
   __node_pointer __rt         = __root();
   while (__rt != nullptr) {
     if (value_comp()(__k, __rt->__value_)) {
-      __result = static_cast<__end_node_pointer>(__rt);
+      __result = __rt;
       __rt     = static_cast<__node_pointer>(__rt->__left_);
     } else if (value_comp()(__rt->__value_, __k))
       __rt = static_cast<__node_pointer>(__rt->__right_);
     else
       return std::distance(
-          __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)),
+          __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
           __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
   }
   return 0;
@@ -2092,7 +2091,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator
 __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
   while (__root != nullptr) {
     if (!value_comp()(__root->__value_, __v)) {
-      __result = static_cast<__end_node_pointer>(__root);
+      __result = __root;
       __root   = static_cast<__node_pointer>(__root->__left_);
     } else
       __root = static_cast<__node_pointer>(__root->__right_);
@@ -2106,7 +2105,7 @@ typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare,
     const _Key& __v, __node_pointer __root, __end_node_pointer __result) const {
   while (__root != nullptr) {
     if (!value_comp()(__root->__value_, __v)) {
-      __result = static_cast<__end_node_pointer>(__root);
+      __result = __root;
       __root   = static_cast<__node_pointer>(__root->__left_);
     } else
       __root = static_cast<__node_pointer>(__root->__right_);
@@ -2120,7 +2119,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator
 __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
   while (__root != nullptr) {
     if (value_comp()(__v, __root->__value_)) {
-      __result = static_cast<__end_node_pointer>(__root);
+      __result = __root;
       __root   = static_cast<__node_pointer>(__root->__left_);
     } else
       __root = static_cast<__node_pointer>(__root->__right_);
@@ -2134,7 +2133,7 @@ typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare,
     const _Key& __v, __node_pointer __root, __end_node_pointer __result) const {
   while (__root != nullptr) {
     if (value_comp()(__v, __root->__value_)) {
-      __result = static_cast<__end_node_pointer>(__root);
+      __result = __root;
       __root   = static_cast<__node_pointer>(__root->__left_);
     } else
       __root = static_cast<__node_pointer>(__root->__right_);
@@ -2151,14 +2150,12 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) {
   __node_pointer __rt         = __root();
   while (__rt != nullptr) {
     if (value_comp()(__k, __rt->__value_)) {
-      __result = static_cast<__end_node_pointer>(__rt);
+      __result = __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(iterator(__rt),
-                 iterator(__rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_))
-                                                    : __result));
+      return _Pp(iterator(__rt), iterator(__rt->__right_ != nullptr ? std::__tree_min(__rt->__right_) : __result));
   }
   return _Pp(iterator(__result), iterator(__result));
 }
@@ -2173,15 +2170,13 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const {
   __node_pointer __rt         = __root();
   while (__rt != nullptr) {
     if (value_comp()(__k, __rt->__value_)) {
-      __result = static_cast<__end_node_pointer>(__rt);
+      __result = __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(
-          const_iterator(__rt),
-          const_iterator(
-              __rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result));
+      return _Pp(const_iterator(__rt),
+                 const_iterator(__rt->__right_ != nullptr ? std::__tree_min(__rt->__right_) : __result));
   }
   return _Pp(const_iterator(__result), const_iterator(__result));
 }
@@ -2195,12 +2190,12 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) {
   __node_pointer __rt     = __root();
   while (__rt != nullptr) {
     if (value_comp()(__k, __rt->__value_)) {
-      __result = static_cast<__end_node_pointer>(__rt);
+      __result = __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_), static_cast<__end_node_pointer>(__rt)),
+      return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
                  __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
   }
   return _Pp(iterator(__result), iterator(__result));
@@ -2216,12 +2211,12 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const {
   __node_pointer __rt     = __root();
   while (__rt != nullptr) {
     if (value_comp()(__k, __rt->__value_)) {
-      __result = static_cast<__end_node_pointer>(__rt);
+      __result = __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_), static_cast<__end_node_pointer>(__rt)),
+      return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt),
                  __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result));
   }
   return _Pp(const_iterator(__result), const_iterator(__result));
@@ -2233,9 +2228,9 @@ __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT {
   __node_pointer __np = __p.__get_np();
   if (__begin_node_ == __p.__ptr_) {
     if (__np->__right_ != nullptr)
-      __begin_node_ = static_cast<__end_node_pointer>(__np->__right_);
+      __begin_node_ = __np->__right_;
     else
-      __begin_node_ = static_cast<__end_node_pointer>(__np->__parent_);
+      __begin_node_ = __np->__parent_;
   }
   --__size_;
   std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__np));
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 6daa7fbbc03c2..c783ff4a96460 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -363,7 +363,7 @@ class __forward_list_iterator {
   _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__begin_node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
 
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__node_pointer __p) _NOEXCEPT
-      : __ptr_(std::__static_fancy_pointer_cast<__begin_node_pointer>(__p)) {}
+      : __ptr_(__p) {}
 
   template <class, class>
   friend class forward_list;
@@ -380,14 +380,14 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
 
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
-    return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value();
+    return static_cast<__node_pointer>(__ptr_)->__get_value();
   }
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
-    return pointer_traits<pointer>::pointer_to(std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value());
+    return pointer_traits<pointer>::pointer_to(static_cast<__node_pointer>(__ptr_)->__get_value());
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator& operator++() {
-    __ptr_ = std::__static_fancy_pointer_cast<__begin_node_pointer>(__ptr_->__next_);
+    __ptr_ = __ptr_->__next_;
     return *this;
   }
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator operator++(int) {
@@ -425,10 +425,6 @@ class __forward_list_const_iterator {
   _LIBCPP_CONSTEXPR_SINCE_CXX26
   _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__begin_node_pointer __p) _NOEXCEPT : __ptr_(__p) {}
 
-  _LIBCPP_CONSTEXPR_SINCE_CXX26
-  _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__node_pointer __p) _NOEXCEPT
-      : __ptr_(std::__static_fancy_pointer_cast<__begin_node_pointer>(__p)) {}
-
   template <class, class>
   friend class forward_list;
 
@@ -444,14 +440,14 @@ public:
   __forward_list_const_iterator(__forward_list_iterator<__node_pointer> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
 
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
-    return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value();
+    return static_cast<__node_pointer>(__ptr_)->__get_value();
   }
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
-    return pointer_traits<pointer>::pointer_to(std::__static_fancy_pointer_cast<__node_pointer>(__ptr_)->__get_value());
+    return pointer_traits<pointer>::pointer_to(static_cast<__node_pointer>(__ptr_)->__get_value());
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator& operator++() {
-    __ptr_ = std::__static_fancy_pointer_cast<__begin_node_pointer>(__ptr_->__next_);
+    __ptr_ = __ptr_->__next_;
     return *this;
   }
   _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator operator++(int) {
@@ -943,8 +939,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 inline forward_list<_Tp, _Alloc>::forward_list(con
 template <class _Tp, class _Alloc>
 _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(size_type __n) {
   if (__n > 0) {
-    for (__begin_node_pointer __p = __base::__before_begin(); __n > 0;
-         --__n, __p = std::__static_fancy_pointer_cast<__begin_node_pointer>(__p->__next_)) {
+    for (__begin_node_pointer __p = __base::__before_begin(); __n > 0; --__n, __p = __p->__next_) {
       __p->__next_ = this->__create_node(/* next = */ nullptr);
     }
   }
@@ -955,8 +950,7 @@ template <class _Tp, class _Alloc>
 _LIBCPP_CONSTEXPR_SINCE_CXX26 forward_list<_Tp, _Alloc>::forward_list(size_type __n, const allocator_type& __base_alloc)
     : __base(__base_alloc) {
   if (__n > 0) {
-    for (__begin_node_pointer __p = __base::__before_begin(); __n > 0;
-         --__n, __p = std::__static_fancy_pointer_cast<__begin_node_pointer>(__p->__next_)) {
+    for (__begin_node_pointer __p = __base::__before_begin(); __n > 0; --__n, __p = __p->__next_) {
       __p->__next_ = this->__create_node(/* next = */ nullptr);
     }
   }
@@ -1198,7 +1192,7 @@ forward_list<_Tp, _Alloc>::__insert_after(const_iterator __p, size_type __n, _Ar
 #  endif // _LIBCPP_HAS_EXCEPTIONS
     __last->__next_ = __r->__next_;
     __r->__next_    = __first;
-    __r             = std::__static_fancy_pointer_cast<__begin_node_pointer>(__last);
+    __r             = __last;
   }
   return iterator(__r);
 }
@@ -1239,7 +1233,7 @@ forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _Inp
 
     __last->__next_ = __r->__next_;
     __r->__next_    = __first;
-    __r             = std::__static_fancy_pointer_cast<__begin_node_pointer>(__last);
+    __r             = __last;
   }
 
   return iterator(__r);
@@ -1258,7 +1252,7 @@ forward_list<_Tp, _Alloc>::erase_after(const_iterator __f) {
 template <class _Tp, class _Alloc>
 _LIBCPP_CONSTEXPR_SINCE_CXX26 typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::erase_after(const_iterator __f, const_iterator __l) {
-  __node_pointer __e = std::__static_fancy_pointer_cast<__node_pointer>(__l.__ptr_);
+  __node_pointer __e = static_cast<__node_pointer>(__l.__ptr_);
   if (__f != __l) {
     __begin_node_pointer __bp = __f.__ptr_;
 
@@ -1324,7 +1318,7 @@ forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& /*__ot
   if (__p != __i && __p != __lm1) {
     __i.__ptr_->__next_   = __lm1.__ptr_->__next_;
     __lm1.__ptr_->__next_ = __p.__ptr_->__next_;
-    __p.__ptr_->__next_   = std::__static_fancy_pointer_cast<__node_pointer>(__lm1.__ptr_);
+    __p.__ptr_->__next_   = static_cast<__node_pointer>(__lm1.__ptr_);
   }
 }
 
@@ -1338,7 +1332,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void forward_list<_Tp, _Alloc>::splice_after(
     if (__f != __lm1) {
       __lm1.__ptr_->__next_ = __p.__ptr_->__next_;
       __p.__ptr_->__next_   = __f.__ptr_->__next_;
-      __f.__ptr_->__next_   = std::__static_fancy_pointer_cast<__node_pointer>(__l.__ptr_);
+      __f.__ptr_->__next_   = static_cast<__node_pointer>(__l.__ptr_);
     }
   }
 }
@@ -1418,7 +1412,7 @@ forward_list<_Tp, _Alloc>::unique(_BinaryPredicate __binary_pred) {
     iterator __j = std::next(__i);
     for (; __j != __e && __binary_pred(*__i, *__j); ++__j)
       ++__count_removed;
-    if (__i.__ptr_->__next_ != std::__static_fancy_pointer_cast<__node_pointer>(__j.__ptr_))
+    if (__i.__ptr_->__next_ != static_cast<__node_pointer>(__j.__ptr_))
       __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j);
     __i = __j;
   }
@@ -1498,7 +1492,7 @@ forward_list<_Tp, _Alloc>::__sort(__node_pointer __f1, difference_type __sz, _Co
   }
   difference_type __sz1 = __sz / 2;
   difference_type __sz2 = __sz - __sz1;
-  __node_pointer __t    = std::__static_fancy_pointer_cast<__node_pointer>(std::next(iterator(__f1), __sz1 - 1).__ptr_);
+  __node_pointer __t    = static_cast<__node_pointer>(std::next(iterator(__f1), __sz1 - 1).__ptr_);
   __node_pointer __f2   = __t->__next_;
   __t->__next_          = nullptr;
   return __merge(__sort(__f1, __sz1, __comp), __sort(__f2, __sz2, __comp), __comp);
diff --git a/libcxx/test/support/min_allocator.h b/libcxx/test/support/min_allocator.h
index 16775649f55cf..f4b8cf17cc2de 100644
--- a/libcxx/test/support/min_allocator.h
+++ b/libcxx/test/support/min_allocator.h
@@ -221,6 +221,13 @@ class min_pointer {
   TEST_CONSTEXPR_CXX14 min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {}
   TEST_CONSTEXPR_CXX14 explicit min_pointer(min_pointer<void, ID> p) TEST_NOEXCEPT : ptr_(static_cast<T*>(p.ptr_)) {}
 
+  template <class U, std::enable_if<std::is_convertible<U*, T*>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 min_pointer(min_pointer<U, ID> p) TEST_NOEXCEPT : ptr_(p.ptr_) {}
+
+  template <class U,
+            std::enable_if<!std::is_convertible<U*, T*>::value && std::is_constructible<U*, T*>::value, int>::type = 0>
+  explicit TEST_CONSTEXPR_CXX14 min_pointer(min_pointer<U, ID> p) TEST_NOEXCEPT : ptr_(static_cast<T*>(p.ptr_)) {}
+
   TEST_CONSTEXPR_CXX14 explicit operator bool() const { return ptr_ != nullptr; }
 
   typedef std::ptrdiff_t difference_type;



More information about the libcxx-commits mailing list