[libcxx-commits] [libcxx] [libc++] Remove UB from std::map __tree_node constructor (PR #153908)
Vinay Deshmukh via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Aug 15 18:03:56 PDT 2025
https://github.com/vinay-deshmukh updated https://github.com/llvm/llvm-project/pull/153908
>From 2f689f97b6c729f03f37e51c941c32186e9d3565 Mon Sep 17 00:00:00 2001
From: Vinay Deshmukh <32487576+vinay-deshmukh at users.noreply.github.com>
Date: Wed, 13 Aug 2025 06:49:44 -0400
Subject: [PATCH 1/5] 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 <class _Alloc, class... _Args>
+ 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 at users.noreply.github.com>
Date: Fri, 15 Aug 2025 20:46:20 -0400
Subject: [PATCH 2/5] 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 <class _Alloc, class... _Args>
explicit __tree_node(_Alloc& __na, _Args&&... __args) {
>From 99c2829166a093ac57479a0b8cb7fbed806cf00c Mon Sep 17 00:00:00 2001
From: Vinay Deshmukh <32487576+vinay-deshmukh at users.noreply.github.com>
Date: Fri, 15 Aug 2025 20:53:57 -0400
Subject: [PATCH 3/5] 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 <class _Alloc, class... _Args>
explicit __tree_node(_Alloc& __na, _Args&&... __args) {
>From 5afe3a4b2ca319491fe05e57e6a46eae4add233b Mon Sep 17 00:00:00 2001
From: Vinay Deshmukh <32487576+vinay-deshmukh at users.noreply.github.com>
Date: Fri, 15 Aug 2025 20:54:06 -0400
Subject: [PATCH 4/5] 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 at users.noreply.github.com>
Date: Fri, 15 Aug 2025 21:03:36 -0400
Subject: [PATCH 5/5] 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>::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>::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>::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>::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<typename __tree<_Tp, _Compare, _Allocator>::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 <class _Tp, class _Compare, class _Allocator>
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 <class _Tp, class _Compare, class _Allocator>
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 <class _Key>
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 <class _Key>
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 <class _Key>
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 <class _Key>
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)),
More information about the libcxx-commits
mailing list