llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

<details>
<summary>Changes</summary>



---

Patch is 115.37 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/147679.diff


5 Files Affected:

- (modified) libcxx/include/__tree (+124-106) 
- (modified) 
libcxx/test/libcxx/containers/associative/tree_balance_after_insert.pass.cpp 
(+258-255) 
- (modified) 
libcxx/test/libcxx/containers/associative/tree_left_rotate.pass.cpp (+1) 
- (modified) libcxx/test/libcxx/containers/associative/tree_remove.pass.cpp 
(+246-242) 
- (modified) 
libcxx/test/libcxx/containers/associative/tree_right_rotate.pass.cpp (+1) 


``````````diff
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 9d4ba3ad0639c..6b025bcf3496d 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -77,6 +77,11 @@ class __map_iterator;
 template <class _TreeIterator>
 class __map_const_iterator;
 
+enum class __tree_color : bool {
+  __red = false,
+  __black = true,
+};
+
 /*
 
 _NodePtr algorithms
@@ -102,7 +107,7 @@ __root, have a non-null __parent_ field.
 // Precondition:  __x != nullptr.
 template <class _NodePtr>
 inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT 
{
-  return __x == __x->__parent_->__left_;
+  return __x == __x->__get_parent()->__left_;
 }
 
 // Determines if the subtree rooted at __x is a proper red black subtree.  If
@@ -110,6 +115,8 @@ inline _LIBCPP_HIDE_FROM_ABI bool 
__tree_is_left_child(_NodePtr __x) _NOEXCEPT {
 //    __x is an improper subtree, returns 0.
 template <class _NodePtr>
 unsigned __tree_sub_invariant(_NodePtr __x) {
+  using enum __tree_color;
+
   if (__x == nullptr)
     return 1;
   // parent consistency checked by caller
@@ -123,10 +130,10 @@ unsigned __tree_sub_invariant(_NodePtr __x) {
   if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr)
     return 0;
   // If this is red, neither child can be red
-  if (!__x->__is_black_) {
-    if (__x->__left_ && !__x->__left_->__is_black_)
+  if (__x->__color_ == __red) {
+    if (__x->__left_ && __x->__left_->__color_ == __red)
       return 0;
-    if (__x->__right_ && !__x->__right_->__is_black_)
+    if (__x->__right_ && __x->__right_->__color_ == __red)
       return 0;
   }
   unsigned __h = std::__tree_sub_invariant(__x->__left_);
@@ -134,7 +141,7 @@ unsigned __tree_sub_invariant(_NodePtr __x) {
     return 0; // invalid left subtree
   if (__h != std::__tree_sub_invariant(__x->__right_))
     return 0;                    // invalid or different height right subtree
-  return __h + __x->__is_black_; // return black height of this node
+  return __h + (__x->__color_ == __black ? 1 : 0); // return black height of 
this node
 }
 
 // Determines if the red black tree rooted at __root is a proper red black 
tree.
@@ -150,7 +157,7 @@ _LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr 
__root) {
   if (!std::__tree_is_left_child(__root))
     return false;
   // root must be black
-  if (!__root->__is_black_)
+  if (__root->__color_ == __tree_color::__red)
     return false;
   // do normal node checks
   return std::__tree_sub_invariant(__root) != 0;
@@ -192,7 +199,7 @@ inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr 
__tree_next_iter(_NodePtr __x) _NOEXCEP
     return static_cast<_EndNodePtr>(std::__tree_min(__x->__right_));
   while (!std::__tree_is_left_child(__x))
     __x = __x->__parent_unsafe();
-  return static_cast<_EndNodePtr>(__x->__parent_);
+  return static_cast<_EndNodePtr>(__x->__get_parent());
 }
 
 // Returns:  pointer to the previous in-order node before __x.
@@ -236,9 +243,9 @@ _LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) 
_NOEXCEPT {
   __x->__right_ = __y->__left_;
   if (__x->__right_ != nullptr)
     __x->__right_->__set_parent(__x);
-  __y->__parent_ = __x->__parent_;
+  __y->__set_parent(__x->__get_parent());
   if (std::__tree_is_left_child(__x))
-    __x->__parent_->__left_ = __y;
+    __x->__get_parent()->__left_ = __y;
   else
     __x->__parent_unsafe()->__right_ = __y;
   __y->__left_ = __x;
@@ -255,9 +262,9 @@ _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr 
__x) _NOEXCEPT {
   __x->__left_ = __y->__right_;
   if (__x->__left_ != nullptr)
     __x->__left_->__set_parent(__x);
-  __y->__parent_ = __x->__parent_;
+  __y->__set_parent(__x->__get_parent());
   if (std::__tree_is_left_child(__x))
-    __x->__parent_->__left_ = __y;
+    __x->__get_parent()->__left_ = __y;
   else
     __x->__parent_unsafe()->__right_ = __y;
   __y->__right_ = __x;
@@ -275,46 +282,47 @@ template <class _NodePtr>
 _LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, 
_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be 
null");
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf");
-  __x->__is_black_ = __x == __root;
-  while (__x != __root && !__x->__parent_unsafe()->__is_black_) {
-    // __x->__parent_ != __root because __x->__parent_->__is_black == false
+  using enum __tree_color;
+  __x->__set_color(__x == __root ? __black : __red);
+  while (__x != __root && __x->__parent_unsafe()->__get_color() == __red) {
+    // __x->__parent_ != __root because __x->__parent_->__get_color() == __red
     if (std::__tree_is_left_child(__x->__parent_unsafe())) {
       _NodePtr __y = __x->__parent_unsafe()->__parent_unsafe()->__right_;
-      if (__y != nullptr && !__y->__is_black_) {
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = true;
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = __x == __root;
-        __y->__is_black_ = true;
+      if (__y != nullptr && __y->__get_color() == __red) {
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__black);
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__x == __root ? __black : __red);
+        __y->__set_color(__black);
       } else {
         if (!std::__tree_is_left_child(__x)) {
           __x = __x->__parent_unsafe();
           std::__tree_left_rotate(__x);
         }
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = true;
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = false;
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__black);
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__red);
         std::__tree_right_rotate(__x);
         break;
       }
     } else {
-      _NodePtr __y = __x->__parent_unsafe()->__parent_->__left_;
-      if (__y != nullptr && !__y->__is_black_) {
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = true;
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = __x == __root;
-        __y->__is_black_ = true;
+      _NodePtr __y = __x->__parent_unsafe()->__get_parent()->__left_;
+      if (__y != nullptr && __y->__get_color() == __red) {
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__black);
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__x == __root ? __black : __red);
+        __y->__set_color(__black);
       } else {
         if (std::__tree_is_left_child(__x)) {
           __x = __x->__parent_unsafe();
           std::__tree_right_rotate(__x);
         }
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = true;
-        __x              = __x->__parent_unsafe();
-        __x->__is_black_ = false;
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__black);
+        __x = __x->__parent_unsafe();
+        __x->__set_color(__red);
         std::__tree_left_rotate(__x);
         break;
       }
@@ -332,6 +340,9 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
   _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null");
   _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be 
null");
   _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants 
should hold");
+
+  using enum __tree_color;
+
   // __z will be removed from the tree.  Client still needs to 
destruct/deallocate it
   // __y is either __z, or if __z has two children, __tree_next(__z).
   // __y will have at most one child.
@@ -343,9 +354,9 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
   _NodePtr __w = nullptr;
   // link __x to __y's parent, and find __w
   if (__x != nullptr)
-    __x->__parent_ = __y->__parent_;
+    __x->__set_parent(__y->__get_parent());
   if (std::__tree_is_left_child(__y)) {
-    __y->__parent_->__left_ = __x;
+    __y->__get_parent()->__left_ = __x;
     if (__y != __root)
       __w = __y->__parent_unsafe()->__right_;
     else
@@ -353,16 +364,16 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
   } else {
     __y->__parent_unsafe()->__right_ = __x;
     // __y can't be root if it is a right child
-    __w = __y->__parent_->__left_;
+    __w = __y->__get_parent()->__left_;
   }
-  bool __removed_black = __y->__is_black_;
+  bool __removed_black = __y->__get_color() == __black;
   // If we didn't remove __z, do so now by splicing in __y for __z,
   //    but copy __z's color.  This does not impact __x or __w.
   if (__y != __z) {
     // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr
-    __y->__parent_ = __z->__parent_;
+    __y->__set_parent(__z->__get_parent());
     if (std::__tree_is_left_child(__z))
-      __y->__parent_->__left_ = __y;
+      __y->__get_parent()->__left_ = __y;
     else
       __y->__parent_unsafe()->__right_ = __y;
     __y->__left_ = __z->__left_;
@@ -370,7 +381,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
     __y->__right_ = __z->__right_;
     if (__y->__right_ != nullptr)
       __y->__right_->__set_parent(__y);
-    __y->__is_black_ = __z->__is_black_;
+    __y->__set_color(__z->__get_color());
     if (__root == __z)
       __root = __y;
   }
@@ -390,7 +401,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
     //   different black heights under left and right pointers.
     // if (__x == __root || __x != nullptr && !__x->__is_black_)
     if (__x != nullptr)
-      __x->__is_black_ = true;
+      __x->__set_color(__black);
     else {
       //  Else __x isn't root, and is "doubly black", even though it may
       //     be null.  __w can not be null here, else the parent would
@@ -400,9 +411,9 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
       while (true) {
         if (!std::__tree_is_left_child(__w)) // if x is left child
         {
-          if (!__w->__is_black_) {
-            __w->__is_black_                    = true;
-            __w->__parent_unsafe()->__is_black_ = false;
+          if (__w->__get_color() == __red) {
+            __w->__set_color(__black);
+            __w->__parent_unsafe()->__set_color(__red);
             std::__tree_left_rotate(__w->__parent_unsafe());
             // __x is still valid
             // reset __root only if necessary
@@ -412,40 +423,40 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
             __w = __w->__left_->__right_;
           }
           // __w->__is_black_ is now true, __w may have null children
-          if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
-              (__w->__right_ == nullptr || __w->__right_->__is_black_)) {
-            __w->__is_black_ = false;
-            __x              = __w->__parent_unsafe();
+          if ((__w->__left_ == nullptr || __w->__left_->__get_color() == 
__black) &&
+              (__w->__right_ == nullptr || __w->__right_->__get_color() == 
__black)) {
+            __w->__set_color(__red);
+            __x = __w->__parent_unsafe();
             // __x can no longer be null
-            if (__x == __root || !__x->__is_black_) {
-              __x->__is_black_ = true;
+            if (__x == __root || __x->__get_color() == __red) {
+              __x->__set_color(__black);
               break;
             }
             // reset sibling, and it still can't be null
-            __w = std::__tree_is_left_child(__x) ? 
__x->__parent_unsafe()->__right_ : __x->__parent_->__left_;
+            __w = std::__tree_is_left_child(__x) ? 
__x->__parent_unsafe()->__right_ : __x->__get_parent()->__left_;
             // continue;
           } else // __w has a red child
           {
-            if (__w->__right_ == nullptr || __w->__right_->__is_black_) {
+            if (__w->__right_ == nullptr || __w->__right_->__get_color() == 
__black) {
               // __w left child is non-null and red
-              __w->__left_->__is_black_ = true;
-              __w->__is_black_          = false;
+              __w->__left_->__set_color(__black);
+              __w->__set_color(__red);
               std::__tree_right_rotate(__w);
               // __w is known not to be root, so root hasn't changed
               // reset sibling, and it still can't be null
               __w = __w->__parent_unsafe();
             }
             // __w has a right red child, left child may be null
-            __w->__is_black_                    = 
__w->__parent_unsafe()->__is_black_;
-            __w->__parent_unsafe()->__is_black_ = true;
-            __w->__right_->__is_black_          = true;
+            __w->__set_color(__w->__parent_unsafe()->__get_color());
+            __w->__parent_unsafe()->__set_color(__black);
+            __w->__right_->__set_color(__black);
             std::__tree_left_rotate(__w->__parent_unsafe());
             break;
           }
         } else {
-          if (!__w->__is_black_) {
-            __w->__is_black_                    = true;
-            __w->__parent_unsafe()->__is_black_ = false;
+          if (__w->__get_color() == __red) {
+            __w->__set_color(__black);
+            __w->__parent_unsafe()->__set_color(__red);
             std::__tree_right_rotate(__w->__parent_unsafe());
             // __x is still valid
             // reset __root only if necessary
@@ -455,33 +466,33 @@ _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, 
_NodePtr __z) _NOEXCEP
             __w = __w->__right_->__left_;
           }
           // __w->__is_black_ is now true, __w may have null children
-          if ((__w->__left_ == nullptr || __w->__left_->__is_black_) &&
-              (__w->__right_ == nullptr || __w->__right_->__is_black_)) {
-            __w->__is_black_ = false;
-            __x              = __w->__parent_unsafe();
+          if ((__w->__left_ == nullptr || __w->__left_->__get_color() == 
__black) &&
+              (__w->__right_ == nullptr || __w->__right_->__get_color() == 
__black)) {
+            __w->__set_color(__red);
+            __x = __w->__parent_unsafe();
             // __x can no longer be null
-            if (!__x->__is_black_ || __x == __root) {
-              __x->__is_black_ = true;
+            if (__x->__get_color() == __red || __x == __root) {
+              __x->__set_color(__black);
               break;
             }
             // reset sibling, and it still can't be null
-            __w = std::__tree_is_left_child(__x) ? 
__x->__parent_unsafe()->__right_ : __x->__parent_->__left_;
+            __w = std::__tree_is_left_child(__x) ? 
__x->__parent_unsafe()->__right_ : __x->__get_parent()->__left_;
             // continue;
           } else // __w has a red child
           {
-            if (__w->__left_ == nullptr || __w->__left_->__is_black_) {
+            if (__w->__left_ == nullptr || __w->__left_->__get_color() == 
__black) {
               // __w right child is non-null and red
-              __w->__right_->__is_black_ = true;
-              __w->__is_black_           = false;
+              __w->__right_->__set_color(__black);
+              __w->__set_color(__red);
               std::__tree_left_rotate(__w);
               // __w is known not to be root, so root hasn't changed
               // reset sibling, and it still can't be null
               __w = __w->__parent_unsafe();
             }
             // __w has a left red child, right child may be null
-            __w->__is_black_                    = 
__w->__parent_unsafe()->__is_black_;
-            __w->__parent_unsafe()->__is_black_ = true;
-            __w->__left_->__is_black_           = true;
+            __w->__set_color(__w->__parent_unsafe()->__get_color());
+            __w->__parent_unsafe()->__set_color(__black);
+            __w->__left_->__set_color(__black);
             std::__tree_right_rotate(__w->__parent_unsafe());
             break;
           }
@@ -563,12 +574,19 @@ public:
   using __end_node_pointer _LIBCPP_NODEBUG = __rebind_pointer_t<_VoidPtr, 
__tree_end_node<pointer> >;
 
   pointer __right_;
+
+private:
   __end_node_pointer __parent_;
-  bool __is_black_;
+  __tree_color __color_;
 
+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(__end_node_pointer __p) { __parent_ 
= __p; }
+  _LIBCPP_HIDE_FROM_ABI __end_node_pointer __get_parent() const { return 
__parent_; }
+  _LIBCPP_HIDE_FROM_ABI __tree_color __get_color() const { return __color_; }
+  _LIBCPP_HIDE_FROM_ABI void __set_color(__tree_color __color) { __color_ = 
__color; }
 
   ~__tree_node_base()                                  = delete;
   __tree_node_base(__tree_node_base const&)            = delete;
@@ -1254,8 +1272,8 @@ private:
     _LIBCPP_HIDE_FROM_ABI ~_DetachedTreeCache() {
       __t_->destroy(__cache_elem_);
       if (__cache_root_) {
-        while (__cache_root_->__parent_ != nullptr)
-          __cache_root_ = 
static_cast<__node_pointer>(__cache_root_->__parent_);
+        while (__cache_root_->__get_parent() != nullptr)
+          __cache_root_ = 
static_cast<__node_pointer>(__cache_root_->__get_parent());
         __t_->destroy(__cache_root_);
       }
     }
@@ -1296,11 +1314,11 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const 
value_compare& __comp, const all
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
 __tree<_Tp, _Compare, 
_Allocator>::_DetachedTreeCache::__detach_from_tree(__tree* __t) _NOEXCEPT {
-  __node_pointer __cache                = 
static_cast<__node_pointer>(__t->__begin_node());
-  __t->__begin_node()                   = __t->__end_node();
-  __t->__end_node()->__left_->__parent_ = nullptr;
-  __t->__end_node()->__left_            = nullptr;
-  __t->size()                           = 0;
+  __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node());
+  __t->__begin_node()    = __t->__end_node();
+  __t->__end_node()->__left_->__set_parent(__parent_pointer(nullptr));
+  __t->__end_node()->__left_ = nullptr;
+  __t->size()                = 0;
   // __cache->__left_ == nullptr
   if (__cache->__right_ != nullptr)
     __cache = static_cast<__node_pointer>(__cache->__right_);
@@ -1316,18 +1334,18 @@ __tree<_Tp, _Compare, 
_Allocator>::_DetachedTreeCache::__detach_from_tree(__tree
 template <class _Tp, class _Compare, class _Allocator>
 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
 __tree<_Tp, _Compare, 
_Allocator>::_DetachedTreeCache::__detach_next(__node_pointer __cache) 
_NOEXCEPT {
-  if (__cache->__parent_ == nullptr)
+  if (__cache->__get_parent() == nullptr)
     return nullptr;
   if (std::__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) {
-    __cache->__parent_->__left_ = nullptr;
-    __cache                     = 
static_cast<__node_pointer>(__cache->__parent_);
+    __cache->__get_parent()->__left_ = nullptr;
+    __cache                     = 
static_cast<__node_pointer>(__cache->__get_parent());
     if (__cache->__right_ == nullptr)
       return __cache;
     return static_cast<__node_pointer>(std::__tree_leaf(__cache->__right_));
   }
   // __cache is right child
   __cache->__parent_unsafe()->__right_ = nullptr;
-  __cache                              = 
static_cast<__node_pointer>(__cache->__parent_);
+  __cache                              = 
static_cast<__node_pointer>(__cache->__get_parent());
   if (__cache->__left_ == nullptr)
     return __cache;
   return static_cast<__node_pointer>(std::__tree_leaf(__cache->__left_));
@@ -1403,10 +1421,10 @@ __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());
-    __t.__begin_node()               = __t.__end_node();
-    __t.__end_node()->__left_        = nullptr;
-    __t.size()                       = 0;
+    
__end_node()->__left_->__set_parent(static_cast<__end_node_pointer>(__end_node()));
+    __t.__begin_node()        = __t.__end_node();
+    __t.__end_node()->__left_ = nullptr;
+    __t.size()                = 0;
   }
 }
 
@@ -1417,13 +1435,13 @@ __t...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/147679
_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to