From 2f689f97b6c729f03f37e51c941c32186e9d3565 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Wed, 13 Aug 2025 06:49:44 -0400 Subject: [PATCH 01/29] use allocator as template arg and allocator_traits, tests passed in cpp26 --- libcxx/include/__tree | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index d154ce1616b93..3fef3efcf78a7 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -582,10 +582,16 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> { public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; + union { __node_value_type __value_; + }; _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + template + explicit __tree_node(_Alloc& __na, _Args&&... __args) { + allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); + } ~__tree_node() = delete; __tree_node(__tree_node const&) = delete; __tree_node& operator=(__tree_node const&) = delete; @@ -1808,7 +1814,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...); + std::__construct_at(std::addressof(*__h), __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } From bbc637ad50a0051e1f46da96bdbef6205e7f846d Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:46:20 -0400 Subject: [PATCH 02/29] remove UB using list --- libcxx/include/__tree | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 3fef3efcf78a7..d860f4c96f467 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -582,11 +582,25 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> { public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; - union { - __node_value_type __value_; - }; + // We allow starting the lifetime of nodes without initializing the value held by the node, + // since that is handled by the map itself in order to be allocator-aware. + # ifndef _LIBCPP_CXX03_LANG + + private: + union { + __node_value_type __value_; + }; + + public: + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + # else + + private: + _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + public: + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } + # endif template explicit __tree_node(_Alloc& __na, _Args&&... __args) { From 99c2829166a093ac57479a0b8cb7fbed806cf00c Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:53:57 -0400 Subject: [PATCH 03/29] cf --- libcxx/include/__tree | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index d860f4c96f467..5245dcdb23434 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -582,25 +582,25 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> { public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; - // We allow starting the lifetime of nodes without initializing the value held by the node, - // since that is handled by the map itself in order to be allocator-aware. - # ifndef _LIBCPP_CXX03_LANG +// We allow starting the lifetime of nodes without initializing the value held by the node, +// since that is handled by the map itself in order to be allocator-aware. +#ifndef _LIBCPP_CXX03_LANG - private: - union { - __node_value_type __value_; - }; +private: + union { + __node_value_type __value_; + }; - public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } - # else +public: + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } +#else - private: - _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; +private: + _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; - public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } - # endif +public: + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } +#endif template explicit __tree_node(_Alloc& __na, _Args&&... __args) { From 5afe3a4b2ca319491fe05e57e6a46eae4add233b Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 20:54:06 -0400 Subject: [PATCH 04/29] doc-fix --- libcxx/include/__tree | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 5245dcdb23434..e1da5e65e3cde 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -582,8 +582,8 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> { public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; -// We allow starting the lifetime of nodes without initializing the value held by the node, -// since that is handled by the map itself in order to be allocator-aware. +// We use a union to avoid initialization during member initialization, which allows us +// to use the allocator from the container to allocate the node itself #ifndef _LIBCPP_CXX03_LANG private: From ca7274486aedc1f13764e5ab88bd0962babc9eb9 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:03:36 -0400 Subject: [PATCH 05/29] Replace __value_ with __get_value() for __tree_node --- libcxx/include/__tree | 91 ++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index e1da5e65e3cde..3fb4769f9bed6 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -572,7 +572,8 @@ public: _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } - ~__tree_node_base() = delete; + _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; + _LIBCPP_HIDE_FROM_ABI ~__tree_node_base() = default; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; @@ -634,7 +635,7 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_)); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value())); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -670,8 +671,8 @@ public: _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__value_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__value_); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator++() { __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); @@ -732,8 +733,8 @@ public: _LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__value_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__value_); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator++() { __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); @@ -1246,7 +1247,7 @@ private: auto __right = __ptr->__right_; - __node_traits::destroy(__alloc_, std::addressof(__ptr->__value_)); + __node_traits::destroy(__alloc_, std::addressof(__ptr->__get_value())); __node_traits::deallocate(__alloc_, __ptr, 1); (*this)(static_cast<__node_pointer>(__right)); @@ -1265,7 +1266,7 @@ private: if (!__src) return nullptr; - __node_holder __new_node = __construct_node(__src->__value_); + __node_holder __new_node = __construct_node(__src->__get_value()); unique_ptr<__node, __tree_deleter> __left( __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)), __node_alloc_); @@ -1296,7 +1297,7 @@ private: return nullptr; } - __assign_value(__dest->__value_, __src->__value_); + __assign_value(__dest->__get_value(), __src->__get_value()); __dest->__is_black_ = __src->__is_black_; // If we already have a left node in the destination tree, reuse it and copy-assign recursively @@ -1437,7 +1438,7 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _ if (__size_ != 0) { _DetachedTreeCache __cache(this); for (; __cache.__get() && __first != __last; ++__first) { - __assign_value(__cache.__get()->__value_, *__first); + __assign_value(__cache.__get()->__get_value(), *__first); __node_insert_multi(__cache.__get()); __cache.__advance(); } @@ -1529,13 +1530,13 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { if (__size_ != 0) { _DetachedTreeCache __cache(this); while (__cache.__get() != nullptr && __t.__size_ != 0) { - __assign_value(__cache.__get()->__value_, std::move(__t.remove(__t.begin())->__value_)); + __assign_value(__cache.__get()->__get_value(), std::move(__t.remove(__t.begin())->__get_value())); __node_insert_multi(__cache.__get()); __cache.__advance(); } } while (__t.__size_ != 0) { - __insert_multi_from_orphaned_node(__e, std::move(__t.remove(__t.begin())->__value_)); + __insert_multi_from_orphaned_node(__e, std::move(__t.remove(__t.begin())->__get_value())); } } } @@ -1603,7 +1604,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent, __node_pointer __nd = __root(); if (__nd != nullptr) { while (true) { - if (value_comp()(__nd->__value_, __v)) { + if (value_comp()(__nd->__get_value(), __v)) { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { @@ -1633,7 +1634,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent __node_pointer __nd = __root(); if (__nd != nullptr) { while (true) { - if (value_comp()(__v, __nd->__value_)) { + if (value_comp()(__v, __nd->__get_value())) { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { @@ -1696,7 +1697,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co __node_base_pointer* __nd_ptr = __root_ptr(); if (__nd != nullptr) { while (true) { - if (value_comp()(__v, __nd->__value_)) { + if (value_comp()(__v, __nd->__get_value())) { if (__nd->__left_ != nullptr) { __nd_ptr = std::addressof(__nd->__left_); __nd = static_cast<__node_pointer>(__nd->__left_); @@ -1704,7 +1705,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co __parent = static_cast<__end_node_pointer>(__nd); return __parent->__left_; } - } else if (value_comp()(__nd->__value_, __v)) { + } else if (value_comp()(__nd->__get_value(), __v)) { if (__nd->__right_ != nullptr) { __nd_ptr = std::addressof(__nd->__right_); __nd = static_cast<__node_pointer>(__nd->__right_); @@ -1839,7 +1840,7 @@ pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; - __node_base_pointer& __child = __find_equal(__parent, __h->__value_); + __node_base_pointer& __child = __find_equal(__parent, __h->__get_value()); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { @@ -1857,7 +1858,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer __dummy; - __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_); + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__get_value()); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); @@ -1872,7 +1873,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __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_); + __node_base_pointer& __child = __find_leaf_high(__parent, __h->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } @@ -1883,7 +1884,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; - __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_); + __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } @@ -1896,7 +1897,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _ __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { - __assign_value(__nd->__value_, __v); + __assign_value(__nd->__get_value(), __v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); __r = __nd; __inserted = true; @@ -1908,7 +1909,7 @@ template 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_); + __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); return iterator(__nd); } @@ -1917,7 +1918,7 @@ template 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_); + __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); return iterator(__nd); } @@ -1944,7 +1945,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n __node_pointer __ptr = __nh.__ptr_; __end_node_pointer __parent; - __node_base_pointer& __child = __find_equal(__parent, __ptr->__value_); + __node_base_pointer& __child = __find_equal(__parent, __ptr->__get_value()); if (__child != nullptr) return _InsertReturnType{iterator(static_cast<__node_pointer>(__child)), false, std::move(__nh)}; @@ -1963,7 +1964,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __ __node_pointer __ptr = __nh.__ptr_; __end_node_pointer __parent; __node_base_pointer __dummy; - __node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, __ptr->__value_); + __node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, __ptr->__get_value()); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr)); @@ -1998,7 +1999,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) { __node_pointer __src_ptr = __i.__get_np(); __end_node_pointer __parent; - __node_base_pointer& __child = __find_equal(__parent, __src_ptr->__value_); + __node_base_pointer& __child = __find_equal(__parent, __src_ptr->__get_value()); ++__i; if (__child != nullptr) continue; @@ -2015,7 +2016,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh return end(); __node_pointer __ptr = __nh.__ptr_; __end_node_pointer __parent; - __node_base_pointer& __child = __find_leaf_high(__parent, __ptr->__value_); + __node_base_pointer& __child = __find_leaf_high(__parent, __ptr->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr)); __nh.__release_ptr(); return iterator(__ptr); @@ -2030,7 +2031,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_); + __node_base_pointer& __child = __find_leaf(__hint, __parent, __ptr->__get_value()); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr)); __nh.__release_ptr(); return iterator(__ptr); @@ -2044,7 +2045,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) { __node_pointer __src_ptr = __i.__get_np(); __end_node_pointer __parent; - __node_base_pointer& __child = __find_leaf_high(__parent, __src_ptr->__value_); + __node_base_pointer& __child = __find_leaf_high(__parent, __src_ptr->__get_value()); ++__i; __source.__remove_node_pointer(__src_ptr); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__src_ptr)); @@ -2099,9 +2100,9 @@ typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_value(), __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return 1; @@ -2116,10 +2117,10 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_value(), __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return std::distance( @@ -2134,7 +2135,7 @@ template 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)) { + if (!value_comp()(__root->__get_value(), __v)) { __result = static_cast<__end_node_pointer>(__root); __root = static_cast<__node_pointer>(__root->__left_); } else @@ -2148,7 +2149,7 @@ template typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { - if (!value_comp()(__root->__value_, __v)) { + if (!value_comp()(__root->__get_value(), __v)) { __result = static_cast<__end_node_pointer>(__root); __root = static_cast<__node_pointer>(__root->__left_); } else @@ -2162,7 +2163,7 @@ template 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_)) { + if (value_comp()(__v, __root->__get_value())) { __result = static_cast<__end_node_pointer>(__root); __root = static_cast<__node_pointer>(__root->__left_); } else @@ -2176,7 +2177,7 @@ template typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { - if (value_comp()(__v, __root->__value_)) { + if (value_comp()(__v, __root->__get_value())) { __result = static_cast<__end_node_pointer>(__root); __root = static_cast<__node_pointer>(__root->__left_); } else @@ -2193,10 +2194,10 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_value(), __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), @@ -2215,10 +2216,10 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_value(), __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp( @@ -2237,10 +2238,10 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_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)), @@ -2258,10 +2259,10 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__value_)) { + if (value_comp()(__k, __rt->__get_value())) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__value_, __k)) + } else if (value_comp()(__rt->__get_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)), From 47b71f8220c5f6c64d126c427cdd94cbaff68af3 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:06:19 -0400 Subject: [PATCH 06/29] miss typo --- libcxx/include/__tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 3fb4769f9bed6..32d609e7264b8 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -600,7 +600,7 @@ private: _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); } #endif template From d16fabf3ded283e3780d3c1c49f9411b5b3d4be2 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:09:59 -0400 Subject: [PATCH 07/29] fix ctor for cpp03 buffer --- libcxx/include/__tree | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 32d609e7264b8..d53e2ff1a0318 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -23,6 +23,7 @@ #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> +#include <__new/launder.h> #include <__type_traits/can_extract_key.h> #include <__type_traits/copy_cvref.h> #include <__type_traits/enable_if.h> @@ -605,7 +606,12 @@ public: template explicit __tree_node(_Alloc& __na, _Args&&... __args) { + +#ifndef _LIBCPP_CXX03_LANG allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); +#else + allocator_traits<_Alloc>::construct(__na, reinterpret_cast<__node_value_type*>(std::addressof(__buffer_)), std::forward<_Args>(__args)...); +#endif } ~__tree_node() = delete; __tree_node(__tree_node const&) = delete; From dcd4cb49bc98c0abb7d7596fbe185515c2fecbd3 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:13:25 -0400 Subject: [PATCH 08/29] cf --- libcxx/include/__tree | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index d53e2ff1a0318..ca4cfe202d419 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -573,8 +573,8 @@ public: _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } - _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; - _LIBCPP_HIDE_FROM_ABI ~__tree_node_base() = default; + _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; + _LIBCPP_HIDE_FROM_ABI ~__tree_node_base() = default; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; @@ -678,7 +678,9 @@ public: _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(__get_np()->__get_value()); + } _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator++() { __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); @@ -740,7 +742,9 @@ public: _LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(__get_np()->__get_value()); + } _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator++() { __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); From 08f53284bd9cd4d8b44dc1e56ac5be518929342c Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:17:46 -0400 Subject: [PATCH 09/29] rename in map as well --- libcxx/include/map | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libcxx/include/map b/libcxx/include/map index 9f98abef9afe0..df9597f999895 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -741,9 +741,9 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.second)); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.first)); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -1389,7 +1389,7 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) { - __tree_.__insert_unique_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__value_)); + __tree_.__insert_unique_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); } } } @@ -1419,9 +1419,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__value_.first), __k); + __node_traits::construct(__na, std::addressof(__h->__get_value().first), __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__value_.second)); + __node_traits::construct(__na, std::addressof(__h->__get_value().second)); __h.get_deleter().__second_constructed = true; return __h; } @@ -1436,7 +1436,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { __tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } - return __r->__value_.second; + return __r->__get_value().second; } # endif // _LIBCPP_CXX03_LANG @@ -1447,7 +1447,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { __node_base_pointer& __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.second; + return static_cast<__node_pointer>(__child)->__get_value().second; } template @@ -1456,7 +1456,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { __node_base_pointer __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.second; + return static_cast<__node_pointer>(__child)->__get_value().second; } template @@ -1959,7 +1959,7 @@ multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const alloca if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) - __tree_.__insert_multi_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__value_)); + __tree_.__insert_multi_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); } } # endif From 4b5609c580a5b113b3dc0d2e67b60b06573e7859 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:34:36 -0400 Subject: [PATCH 10/29] cf --- libcxx/include/__tree | 8 +++++--- libcxx/include/map | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index ca4cfe202d419..ae66a29f60f58 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -601,16 +601,18 @@ private: _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { + return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); + } #endif template explicit __tree_node(_Alloc& __na, _Args&&... __args) { - #ifndef _LIBCPP_CXX03_LANG allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); #else - allocator_traits<_Alloc>::construct(__na, reinterpret_cast<__node_value_type*>(std::addressof(__buffer_)), std::forward<_Args>(__args)...); + allocator_traits<_Alloc>::construct( + __na, reinterpret_cast<__node_value_type*>(std::addressof(__buffer_)), std::forward<_Args>(__args)...); #endif } ~__tree_node() = delete; diff --git a/libcxx/include/map b/libcxx/include/map index df9597f999895..4dfce70e50e7f 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -1389,7 +1389,8 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) { - __tree_.__insert_unique_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); + __tree_.__insert_unique_from_orphaned_node( + __e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); } } } @@ -1959,7 +1960,8 @@ multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const alloca if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) - __tree_.__insert_multi_from_orphaned_node(__e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); + __tree_.__insert_multi_from_orphaned_node( + __e.__i_, std::move(__m.__tree_.remove(__m.begin().__i_)->__get_value())); } } # endif From d24dbc2571939428a812031b506989decae0c826 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:35:28 -0400 Subject: [PATCH 11/29] include --- libcxx/include/__tree | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index ae66a29f60f58..81bc316486964 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -20,6 +20,7 @@ #include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> +#include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> From 9c4757435b8c5d7e5521ede95817d993a35c3800 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:49:59 -0400 Subject: [PATCH 12/29] more? --- libcxx/include/set | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/set b/libcxx/include/set index c77345bc5dc1f..05c1939dbbabf 100644 --- a/libcxx/include/set +++ b/libcxx/include/set @@ -953,7 +953,7 @@ set<_Key, _Compare, _Allocator>::set(set&& __s, const allocator_type& __a) : __t if (__a != __s.get_allocator()) { const_iterator __e = cend(); while (!__s.empty()) - insert(__e, std::move(__s.__tree_.remove(__s.begin())->__value_)); + insert(__e, std::move(__s.__tree_.remove(__s.begin())->__get_value())); } } @@ -1416,7 +1416,7 @@ multiset<_Key, _Compare, _Allocator>::multiset(multiset&& __s, const allocator_t if (__a != __s.get_allocator()) { const_iterator __e = cend(); while (!__s.empty()) - insert(__e, std::move(__s.__tree_.remove(__s.begin())->__value_)); + insert(__e, std::move(__s.__tree_.remove(__s.begin())->__get_value())); } } From 8b1278ea7c37c0d8bc3ac7694c8f75e13cffbb57 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 16 Aug 2025 09:13:18 -0400 Subject: [PATCH 13/29] hide from abi --- libcxx/include/__tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 81bc316486964..09a7da8943e20 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -608,7 +608,7 @@ public: #endif template - explicit __tree_node(_Alloc& __na, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI explicit __tree_node(_Alloc& __na, _Args&&... __args) { #ifndef _LIBCPP_CXX03_LANG allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); #else From b2416366dbe2d55ee56dc991266131d6ce0d2966 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sun, 17 Aug 2025 09:10:23 -0400 Subject: [PATCH 14/29] terser --- libcxx/include/__tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 09a7da8943e20..b379b1bb1e4aa 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -613,7 +613,7 @@ public: allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); #else allocator_traits<_Alloc>::construct( - __na, reinterpret_cast<__node_value_type*>(std::addressof(__buffer_)), std::forward<_Args>(__args)...); + __na, reinterpret_cast<__node_value_type*>(__buffer_), std::forward<_Args>(__args)...); #endif } ~__tree_node() = delete; From f5cc9c3c8cf47ff634fb2e356516e1e1018af097 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 18 Aug 2025 07:36:10 -0400 Subject: [PATCH 15/29] redundant launder --- libcxx/include/__tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index b379b1bb1e4aa..a0bcaf2408765 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -603,7 +603,7 @@ private: public: _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { - return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); + return *reinterpret_cast<__node_value_type*>(&__buffer_); } #endif From c1a776e69dfe39fb593b707c327b6d73df58ccd7 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 18 Aug 2025 07:37:53 -0400 Subject: [PATCH 16/29] single branch --- libcxx/include/__tree | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index a0bcaf2408765..b2dd538c2ca6d 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -609,12 +609,7 @@ public: template _LIBCPP_HIDE_FROM_ABI explicit __tree_node(_Alloc& __na, _Args&&... __args) { -#ifndef _LIBCPP_CXX03_LANG - allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...); -#else - allocator_traits<_Alloc>::construct( - __na, reinterpret_cast<__node_value_type*>(__buffer_), std::forward<_Args>(__args)...); -#endif + allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); } ~__tree_node() = delete; __tree_node(__tree_node const&) = delete; From 4e905fecc62fc46649e570806fec8c572d8555ba Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:24:38 -0400 Subject: [PATCH 17/29] remove the & from buffer --- libcxx/include/__tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index b2dd538c2ca6d..4cc4e1c905fa8 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -603,7 +603,7 @@ private: public: _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { - return *reinterpret_cast<__node_value_type*>(&__buffer_); + return *reinterpret_cast<__node_value_type*>(__buffer_); } #endif From 225b03cf465124b67d9e84bef50dfa10d99270c1 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:51:44 -0400 Subject: [PATCH 18/29] remove _LIBCPP_STANDALONE_DEBUG --- libcxx/include/__config | 6 ------ libcxx/include/__tree | 5 ++--- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/libcxx/include/__config b/libcxx/include/__config index 77a71b6cf1cae..3b590277eaf3b 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1169,12 +1169,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NO_SPECIALIZATIONS # endif -# if __has_cpp_attribute(_Clang::__standalone_debug__) -# define _LIBCPP_STANDALONE_DEBUG [[_Clang::__standalone_debug__]] -# else -# define _LIBCPP_STANDALONE_DEBUG -# endif - # if __has_cpp_attribute(_Clang::__preferred_name__) # define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]] # else diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 4cc4e1c905fa8..0edac54f4ae53 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -560,8 +560,7 @@ public: }; template -class _LIBCPP_STANDALONE_DEBUG -__tree_node_base : public __tree_end_node<__rebind_pointer_t<_VoidPtr, __tree_node_base<_VoidPtr> > > { +class __tree_node_base : public __tree_end_node<__rebind_pointer_t<_VoidPtr, __tree_node_base<_VoidPtr> > > { public: using pointer = __rebind_pointer_t<_VoidPtr, __tree_node_base>; using __end_node_pointer _LIBCPP_NODEBUG = __rebind_pointer_t<_VoidPtr, __tree_end_node >; @@ -581,7 +580,7 @@ public: }; template -class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> { +class __tree_node : public __tree_node_base<_VoidPtr> { public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; From 1b01b80d3eadab50f69c726315fa277ea26057ba Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:54:54 -0400 Subject: [PATCH 19/29] cf --- libcxx/include/__tree | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 0edac54f4ae53..1cb372bda9643 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -601,9 +601,7 @@ private: _ALIGNAS_TYPE(__node_value_type) unsigned char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { - return *reinterpret_cast<__node_value_type*>(__buffer_); - } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return *reinterpret_cast<__node_value_type*>(__buffer_); } #endif template From 77c15690ba743e85a0d79b03795f34b52c77ed86 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:30:09 -0400 Subject: [PATCH 20/29] Remove ~__tree_node_base() = default; --- libcxx/include/__tree | 1 - 1 file changed, 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 01679c4ed6000..dd11f781bb8eb 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -574,7 +574,6 @@ public: _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; - _LIBCPP_HIDE_FROM_ABI ~__tree_node_base() = default; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; From 0698243df490f831c22f37ca76cb021805bca540 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 1 Sep 2025 13:51:10 -0400 Subject: [PATCH 21/29] Update __hash_node constructor to be similar to __tree_node --- libcxx/include/__hash_table | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 91f660d3491e8..f1601c0d5b058 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -166,7 +166,13 @@ public: } #endif - _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {} + template + _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash, _Alloc& __na, _Args&&... __args) + : _Base(__next), __hash_(__hash) + { + allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); + } + _LIBCPP_HIDE_FROM_ABI ~__hash_node() {} }; @@ -1874,16 +1880,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value - // held inside the node, since we need to use the allocator's construct() method for that. - // + // Begin the lifetime of the node itself and the value_type contained within. + // // We don't use the allocator's construct() method to construct the node itself since the // Cpp17FooInsertable named requirements don't require the allocator's construct() method // to work on anything other than the value_type. - std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0); + std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0, __na, std::forward<_Args>(__args)...); - // Now construct the value_type using the allocator's construct() method. - __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; __h->__hash_ = hash_function()(__h->__get_value()); @@ -1897,8 +1900,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type"); __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash); - __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); + std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash, __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } From 5cd0195d0c9deb3c53bbd66acef6cada36a31997 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 1 Sep 2025 14:15:00 -0400 Subject: [PATCH 22/29] cf --- libcxx/include/__hash_table | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index f1601c0d5b058..89d6353eb057d 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -168,8 +168,7 @@ public: template _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash, _Alloc& __na, _Args&&... __args) - : _Base(__next), __hash_(__hash) - { + : _Base(__next), __hash_(__hash) { allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); } @@ -1880,8 +1879,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - // Begin the lifetime of the node itself and the value_type contained within. - // + // Begin the lifetime of the node itself and the value_type contained within. + // // We don't use the allocator's construct() method to construct the node itself since the // Cpp17FooInsertable named requirements don't require the allocator's construct() method // to work on anything other than the value_type. @@ -1900,7 +1899,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type"); __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash, __na, std::forward<_Args>(__args)...); + std::__construct_at( + std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash, __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } From f7332e660d268370d986911320217e8c33caba5c Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Wed, 3 Sep 2025 20:57:45 -0400 Subject: [PATCH 23/29] delete ~__tree_node_base --- libcxx/include/__tree | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index aac5d4a7e8c99..ab5655d785d96 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -574,6 +574,7 @@ public: _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; + ~__tree_node_base() = delete; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; From 8e9153e5fb889e32284ecc5d584696b42499172a Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Wed, 3 Sep 2025 21:12:07 -0400 Subject: [PATCH 24/29] Revert "delete ~__tree_node_base" This reverts commit f7332e660d268370d986911320217e8c33caba5c. --- libcxx/include/__tree | 1 - 1 file changed, 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index ab5655d785d96..aac5d4a7e8c99 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -574,7 +574,6 @@ public: _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; - ~__tree_node_base() = delete; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; From 3ded53507651be46f2c109f37016eb48a6d0280e Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 6 Sep 2025 10:17:52 -0400 Subject: [PATCH 25/29] Default to nullptr, and assign __hash during construction --- libcxx/include/__hash_table | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 89d6353eb057d..087834aed16be 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -167,8 +167,8 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash, _Alloc& __na, _Args&&... __args) - : _Base(__next), __hash_(__hash) { + _LIBCPP_HIDE_FROM_ABI explicit __hash_node(size_t __hash, _Alloc& __na, _Args&&... __args) + : _Base(nullptr), __hash_(__hash) { allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); } @@ -1884,11 +1884,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { // We don't use the allocator's construct() method to construct the node itself since the // Cpp17FooInsertable named requirements don't require the allocator's construct() method // to work on anything other than the value_type. - std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0, __na, std::forward<_Args>(__args)...); + std::__construct_at(std::addressof(*__h), /* hash = */ hash_function()(__h->__get_value()), __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; - __h->__hash_ = hash_function()(__h->__get_value()); return __h; } @@ -1900,7 +1899,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); std::__construct_at( - std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash, __na, std::forward<_Args>(__args)...); + std::addressof(*__h), /* hash = */ __hash, __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } From ccc9292ea119753017e06fc17f6878b19edbb2f2 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sun, 7 Sep 2025 00:43:20 -0400 Subject: [PATCH 26/29] fix eager reduction... --- libcxx/include/__hash_table | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 087834aed16be..50c17be4dc4c0 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -1884,10 +1884,11 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { // We don't use the allocator's construct() method to construct the node itself since the // Cpp17FooInsertable named requirements don't require the allocator's construct() method // to work on anything other than the value_type. - std::__construct_at(std::addressof(*__h), /* hash = */ hash_function()(__h->__get_value()), __na, std::forward<_Args>(__args)...); + std::__construct_at(std::addressof(*__h), /* hash = */ 0, __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; + __h->__hash_ = hash_function()(__h->__get_value()); return __h; } From a59fb8980d8f0de734d8a9c5c0358e7aecf526ed Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sun, 7 Sep 2025 00:52:32 -0400 Subject: [PATCH 27/29] format --- libcxx/include/__hash_table | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 50c17be4dc4c0..503c36e03fa8c 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -1899,8 +1899,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type"); __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - std::__construct_at( - std::addressof(*__h), /* hash = */ __hash, __na, std::forward<_Args>(__args)...); + std::__construct_at(std::addressof(*__h), /* hash = */ __hash, __na, std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } From 117e150d391136330063761f14ec4bcd39946200 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sun, 7 Sep 2025 08:00:02 -0400 Subject: [PATCH 28/29] Fix doc comment, to say construct, not allocate --- libcxx/include/__tree | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__tree b/libcxx/include/__tree index aac5d4a7e8c99..800fc87664713 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -584,7 +584,8 @@ public: using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>; // We use a union to avoid initialization during member initialization, which allows us -// to use the allocator from the container to allocate the node itself +// to use the allocator from the container to construct the `__node_value_type` in the +// memory provided by the union member #ifndef _LIBCPP_CXX03_LANG private: From f0dfc29932f771651710b4b9e5ddb517ca26d899 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh Date: Wed, 10 Sep 2025 06:05:15 -0400 Subject: [PATCH 29/29] After public