[libcxx-commits] [libcxx] [libc++] Refactor node creation and destruction in list and forward_list (PR #65614)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Sep 14 11:45:43 PDT 2023


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/65614:

>From 95b2e16b01b148ca589c0ece3ab5e6041db4178c Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 7 Sep 2023 09:58:42 -0400
Subject: [PATCH] [libc++] Refactor node creation and destruction in list and
 forward_list

This removes a lot of code duplication, makes the code simpler and
prepares the terrain for https://reviews.llvm.org/D101206, which will
fix some UB in the node-based containers.

This also allows removing the dependency of list and forward_list on
unique_ptr by using __allocation_guard instead.
---
 libcxx/include/chrono                         |   2 +
 libcxx/include/forward_list                   | 171 +++++----------
 libcxx/include/list                           | 201 +++++++-----------
 .../test/libcxx/transitive_includes/cxx23.csv |   2 -
 .../test/libcxx/transitive_includes/cxx26.csv |   2 -
 5 files changed, 122 insertions(+), 256 deletions(-)

diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index 2ef7d7d4af2543c..becf95c0d03e6d3 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -846,6 +846,8 @@ constexpr chrono::year                                  operator ""y(unsigned lo
 #  include <bit>
 #  include <concepts>
 #  include <cstring>
+#  include <forward_list>
+#  include <string>
 #endif
 
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER == 20
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 1dbf1a3ca51c9f4..75ac685cc02839e 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -209,12 +209,10 @@ template <class T, class Allocator, class Predicate>
 #include <__memory/addressof.h>
 #include <__memory/allocation_guard.h>
 #include <__memory/allocator.h>
-#include <__memory/allocator_destructor.h>
 #include <__memory/allocator_traits.h>
 #include <__memory/compressed_pair.h>
 #include <__memory/pointer_traits.h>
 #include <__memory/swap_allocator.h>
-#include <__memory/unique_ptr.h>
 #include <__memory_resource/polymorphic_allocator.h>
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
@@ -272,13 +270,12 @@ struct __forward_list_node_value_type<__forward_list_node<_Tp, _VoidPtr> > {
 template <class _NodePtr>
 struct __forward_node_traits {
 
-  typedef __remove_cv_t<
-        typename pointer_traits<_NodePtr>::element_type>        __node;
-  typedef typename __forward_list_node_value_type<__node>::type __node_value_type;
-  typedef _NodePtr                                              __node_pointer;
-  typedef __forward_begin_node<_NodePtr>                        __begin_node;
-  typedef __rebind_pointer_t<_NodePtr, __begin_node>            __begin_node_pointer;
-  typedef __rebind_pointer_t<_NodePtr, void>                    __void_pointer;
+  typedef __remove_cv_t<typename pointer_traits<_NodePtr>::element_type> __node_type;
+  typedef typename __forward_list_node_value_type<__node_type>::type     __node_value_type;
+  typedef _NodePtr                                                       __node_pointer;
+  typedef __forward_begin_node<_NodePtr>                                 __begin_node;
+  typedef __rebind_pointer_t<_NodePtr, __begin_node>                     __begin_node_pointer;
+  typedef __rebind_pointer_t<_NodePtr, void>                             __void_pointer;
 
 #if defined(_LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB)
   typedef __begin_node_pointer __iter_node_pointer;
@@ -423,7 +420,7 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_const_iterator
     typedef _NodeConstPtr _NodePtr;
 
     typedef __forward_node_traits<_NodePtr>         __traits;
-    typedef typename __traits::__node               __node;
+    typedef typename __traits::__node_type          __node_type;
     typedef typename __traits::__node_pointer       __node_pointer;
     typedef typename __traits::__begin_node_pointer __begin_node_pointer;
     typedef typename __traits::__iter_node_pointer  __iter_node_pointer;
@@ -508,9 +505,9 @@ protected:
     typedef _Alloc allocator_type;
 
     typedef typename allocator_traits<allocator_type>::void_pointer  void_pointer;
-    typedef __forward_list_node<value_type, void_pointer>            __node;
+    typedef __forward_list_node<value_type, void_pointer>            __node_type;
     typedef __begin_node_of<value_type, void_pointer>                __begin_node;
-    typedef __rebind_alloc<allocator_traits<allocator_type>, __node> __node_allocator;
+    typedef __rebind_alloc<allocator_traits<allocator_type>, __node_type> __node_allocator;
     typedef allocator_traits<__node_allocator>        __node_traits;
     typedef typename __node_traits::pointer           __node_pointer;
 
@@ -576,6 +573,22 @@ protected:
         {__move_assign_alloc(__x, integral_constant<bool,
               __node_traits::propagate_on_container_move_assignment::value>());}
 
+    template <class ..._Args>
+    _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__node_pointer __next, _Args&& ...__args) {
+        __node_allocator& __a = __alloc();
+        __allocation_guard<__node_allocator> __guard(__a, 1);
+        __guard.__get()->__next_ = __next;
+        __node_traits::construct(__a, std::addressof(__guard.__get()->__value_), std::forward<_Args>(__args)...);
+        return __guard.__release_ptr();
+    }
+
+    template <class ..._Args>
+    _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) {
+        __node_allocator& __a = __alloc();
+        __node_traits::destroy(__a, std::addressof(__node->__value_));
+        __node_traits::deallocate(__a, __node, 1);
+    }
+
 public:
     _LIBCPP_INLINE_VISIBILITY
     void swap(__forward_list_base& __x)
@@ -661,12 +674,10 @@ template <class _Tp, class _Alloc>
 void
 __forward_list_base<_Tp, _Alloc>::clear() _NOEXCEPT
 {
-    __node_allocator& __a = __alloc();
     for (__node_pointer __p = __before_begin()->__next_; __p != nullptr;)
     {
         __node_pointer __next = __p->__next_;
-        __node_traits::destroy(__a, _VSTD::addressof(__p->__value_));
-        __node_traits::deallocate(__a, __p, 1);
+        __delete_node(__p);
         __p = __next;
     }
     __before_begin()->__next_ = nullptr;
@@ -678,7 +689,7 @@ class _LIBCPP_TEMPLATE_VIS forward_list
 {
     typedef __forward_list_base<_Tp, _Alloc> base;
     typedef typename base::__node_allocator  __node_allocator;
-    typedef typename base::__node               __node;
+    typedef typename base::__node_type          __node_type;
     typedef typename base::__node_traits        __node_traits;
     typedef typename base::__node_pointer       __node_pointer;
     typedef typename base::__begin_node_pointer __begin_node_pointer;
@@ -1006,16 +1017,10 @@ forward_list<_Tp, _Alloc>::forward_list(size_type __n)
 {
     if (__n > 0)
     {
-        __node_allocator& __a = base::__alloc();
-        typedef __allocator_destructor<__node_allocator> _Dp;
-        unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1));
         for (__begin_node_pointer __p = base::__before_begin(); __n > 0; --__n,
                                                              __p = __p->__next_as_begin())
         {
-            __h.reset(__node_traits::allocate(__a, 1));
-            __node_traits::construct(__a, _VSTD::addressof(__h->__value_));
-            __h->__next_ = nullptr;
-            __p->__next_ = __h.release();
+            __p->__next_ = this->__create_node(/* next = */nullptr);
         }
     }
 }
@@ -1028,16 +1033,10 @@ forward_list<_Tp, _Alloc>::forward_list(size_type __n,
 {
     if (__n > 0)
     {
-        __node_allocator& __a = base::__alloc();
-        typedef __allocator_destructor<__node_allocator> _Dp;
-        unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1));
         for (__begin_node_pointer __p = base::__before_begin(); __n > 0; --__n,
                                                              __p = __p->__next_as_begin())
         {
-            __h.reset(__node_traits::allocate(__a, 1));
-            __node_traits::construct(__a, _VSTD::addressof(__h->__value_));
-            __h->__next_ = nullptr;
-            __p->__next_ = __h.release();
+            __p->__next_ = this->__create_node(/* next = */nullptr);
         }
     }
 }
@@ -1226,13 +1225,7 @@ void
 #endif
 forward_list<_Tp, _Alloc>::emplace_front(_Args&&... __args)
 {
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_),
-                                  _VSTD::forward<_Args>(__args)...);
-    __h->__next_ = base::__before_begin()->__next_;
-    base::__before_begin()->__next_ = __h.release();
+    base::__before_begin()->__next_ = this->__create_node(/* next = */base::__before_begin()->__next_, std::forward<_Args>(__args)...);
 #if _LIBCPP_STD_VER >= 17
     return base::__before_begin()->__next_->__value_;
 #endif
@@ -1242,12 +1235,7 @@ template <class _Tp, class _Alloc>
 void
 forward_list<_Tp, _Alloc>::push_front(value_type&& __v)
 {
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
-    __h->__next_ = base::__before_begin()->__next_;
-    base::__before_begin()->__next_ = __h.release();
+    base::__before_begin()->__next_ = this->__create_node(/* next = */base::__before_begin()->__next_, std::move(__v));
 }
 
 #endif // _LIBCPP_CXX03_LANG
@@ -1256,23 +1244,16 @@ template <class _Tp, class _Alloc>
 void
 forward_list<_Tp, _Alloc>::push_front(const value_type& __v)
 {
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v);
-    __h->__next_ = base::__before_begin()->__next_;
-    base::__before_begin()->__next_ = __h.release();
+    base::__before_begin()->__next_ = this->__create_node(/* next = */base::__before_begin()->__next_, __v);
 }
 
 template <class _Tp, class _Alloc>
 void
 forward_list<_Tp, _Alloc>::pop_front()
 {
-    __node_allocator& __a = base::__alloc();
     __node_pointer __p = base::__before_begin()->__next_;
     base::__before_begin()->__next_ = __p->__next_;
-    __node_traits::destroy(__a, _VSTD::addressof(__p->__value_));
-    __node_traits::deallocate(__a, __p, 1);
+    this->__delete_node(__p);
 }
 
 #ifndef _LIBCPP_CXX03_LANG
@@ -1283,13 +1264,7 @@ typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::emplace_after(const_iterator __p, _Args&&... __args)
 {
     __begin_node_pointer const __r = __p.__get_begin();
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_),
-                                  _VSTD::forward<_Args>(__args)...);
-    __h->__next_ = __r->__next_;
-    __r->__next_ = __h.release();
+    __r->__next_ = this->__create_node(/* next = */__r->__next_, std::forward<_Args>(__args)...);
     return iterator(__r->__next_);
 }
 
@@ -1298,12 +1273,7 @@ typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, value_type&& __v)
 {
     __begin_node_pointer const __r = __p.__get_begin();
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
-    __h->__next_ = __r->__next_;
-    __r->__next_ = __h.release();
+    __r->__next_ = this->__create_node(/* next = */__r->__next_, std::move(__v));
     return iterator(__r->__next_);
 }
 
@@ -1314,12 +1284,7 @@ typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, const value_type& __v)
 {
     __begin_node_pointer const __r = __p.__get_begin();
-    __node_allocator& __a = base::__alloc();
-    typedef __allocator_destructor<__node_allocator> _Dp;
-    unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
-    __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v);
-    __h->__next_ = __r->__next_;
-    __r->__next_ = __h.release();
+    __r->__next_ = this->__create_node(/* next = */__r->__next_, __v);
     return iterator(__r->__next_);
 }
 
@@ -1328,20 +1293,10 @@ typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n,
                                         const value_type& __v)
 {
-    using _Guard = __allocation_guard<__node_allocator>;
-
     __begin_node_pointer __r = __p.__get_begin();
     if (__n > 0)
     {
-        __node_allocator& __a = base::__alloc();
-
-        __node_pointer __first = nullptr;
-        {
-          _Guard __h(__a, 1);
-          __node_traits::construct(__a, std::addressof(__h.__get()->__value_), __v);
-          __h.__get()->__next_ = nullptr;
-          __first = __h.__release_ptr();
-        }
+        __node_pointer __first = this->__create_node(/* next = */nullptr, __v);
         __node_pointer __last = __first;
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         try
@@ -1349,10 +1304,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n,
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (--__n; __n != 0; --__n, __last = __last->__next_)
             {
-                _Guard __h(__a, 1);
-                __node_traits::construct(__a, std::addressof(__h.__get()->__value_), __v);
-                __h.__get()->__next_ = nullptr;
-                __last->__next_ = __h.__release_ptr();
+                __last->__next_ = this->__create_node(/* next = */nullptr, __v);
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1361,8 +1313,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n,
             while (__first != nullptr)
             {
                 __node_pointer __next = __first->__next_;
-                __node_traits::destroy(__a, _VSTD::addressof(__first->__value_));
-                __node_traits::deallocate(__a, __first, 1);
+                this->__delete_node(__first);
                 __first = __next;
             }
             throw;
@@ -1389,19 +1340,11 @@ template <class _InputIterator, class _Sentinel>
 _LIBCPP_HIDE_FROM_ABI
 typename forward_list<_Tp, _Alloc>::iterator
 forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l) {
-    using _Guard = __allocation_guard<__node_allocator>;
     __begin_node_pointer __r = __p.__get_begin();
 
     if (__f != __l)
     {
-        __node_allocator& __a = base::__alloc();
-        __node_pointer __first = nullptr;
-        {
-          _Guard __h(__a, 1);
-          __node_traits::construct(__a, std::addressof(__h.__get()->__value_), *__f);
-          __h.__get()->__next_ = nullptr;
-          __first = __h.__release_ptr();
-        }
+        __node_pointer __first = this->__create_node(/* next = */nullptr, *__f);
         __node_pointer __last = __first;
 
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
@@ -1410,10 +1353,7 @@ forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _Inp
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_)))
             {
-                _Guard __h(__a, 1);
-                __node_traits::construct(__a, std::addressof(__h.__get()->__value_), *__f);
-                __h.__get()->__next_ = nullptr;
-                __last->__next_ = __h.__release_ptr();
+                __last->__next_ = this->__create_node(/* next = */nullptr, *__f);
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1422,8 +1362,7 @@ forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _Inp
             while (__first != nullptr)
             {
                 __node_pointer __next = __first->__next_;
-                __node_traits::destroy(__a, _VSTD::addressof(__first->__value_));
-                __node_traits::deallocate(__a, __first, 1);
+                this->__delete_node(__first);
                 __first = __next;
             }
             throw;
@@ -1445,9 +1384,7 @@ forward_list<_Tp, _Alloc>::erase_after(const_iterator __f)
     __begin_node_pointer __p = __f.__get_begin();
     __node_pointer __n = __p->__next_;
     __p->__next_ = __n->__next_;
-    __node_allocator& __a = base::__alloc();
-    __node_traits::destroy(__a, _VSTD::addressof(__n->__value_));
-    __node_traits::deallocate(__a, __n, 1);
+    this->__delete_node(__n);
     return iterator(__p->__next_);
 }
 
@@ -1464,12 +1401,10 @@ forward_list<_Tp, _Alloc>::erase_after(const_iterator __f, const_iterator __l)
         if (__n != __e)
         {
             __bp->__next_ = __e;
-            __node_allocator& __a = base::__alloc();
             do
             {
                 __node_pointer __tmp = __n->__next_;
-                __node_traits::destroy(__a, _VSTD::addressof(__n->__value_));
-                __node_traits::deallocate(__a, __n, 1);
+                this->__delete_node(__n);
                 __n = __tmp;
             } while (__n != __e);
         }
@@ -1494,16 +1429,10 @@ forward_list<_Tp, _Alloc>::resize(size_type __n)
         __n -= __sz;
         if (__n > 0)
         {
-            __node_allocator& __a = base::__alloc();
-            typedef __allocator_destructor<__node_allocator> _Dp;
-            unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1));
             for (__begin_node_pointer __ptr = __p.__get_begin(); __n > 0; --__n,
                                                          __ptr = __ptr->__next_as_begin())
             {
-                __h.reset(__node_traits::allocate(__a, 1));
-                __node_traits::construct(__a, _VSTD::addressof(__h->__value_));
-                __h->__next_ = nullptr;
-                __ptr->__next_ = __h.release();
+                __ptr->__next_ = this->__create_node(/* next = */nullptr);
             }
         }
     }
@@ -1526,16 +1455,10 @@ forward_list<_Tp, _Alloc>::resize(size_type __n, const value_type& __v)
         __n -= __sz;
         if (__n > 0)
         {
-            __node_allocator& __a = base::__alloc();
-            typedef __allocator_destructor<__node_allocator> _Dp;
-            unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1));
             for (__begin_node_pointer __ptr = __p.__get_begin(); __n > 0; --__n,
                                                          __ptr = __ptr->__next_as_begin())
             {
-                __h.reset(__node_traits::allocate(__a, 1));
-                __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v);
-                __h->__next_ = nullptr;
-                __ptr->__next_ = __h.release();
+                __ptr->__next_ = this->__create_node(/* next = */nullptr, __v);
             }
         }
     }
@@ -1931,7 +1854,9 @@ _LIBCPP_POP_MACROS
 #  include <algorithm>
 #  include <atomic>
 #  include <concepts>
+#  include <cstdint>
 #  include <cstdlib>
+#  include <cstring>
 #  include <functional>
 #  include <iosfwd>
 #  include <iterator>
diff --git a/libcxx/include/list b/libcxx/include/list
index 77b988cd1ef911b..b02599bc3fe7c3e 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -213,13 +213,12 @@ template <class T, class Allocator, class Predicate>
 #include <__iterator/prev.h>
 #include <__iterator/reverse_iterator.h>
 #include <__memory/addressof.h>
+#include <__memory/allocation_guard.h>
 #include <__memory/allocator.h>
-#include <__memory/allocator_destructor.h>
 #include <__memory/allocator_traits.h>
 #include <__memory/compressed_pair.h>
 #include <__memory/pointer_traits.h>
 #include <__memory/swap_allocator.h>
-#include <__memory/unique_ptr.h>
 #include <__memory_resource/polymorphic_allocator.h>
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
@@ -494,8 +493,8 @@ protected:
     typedef __list_iterator<value_type, __void_pointer>             iterator;
     typedef __list_const_iterator<value_type, __void_pointer>       const_iterator;
     typedef __list_node_base<value_type, __void_pointer>            __node_base;
-    typedef __list_node<value_type, __void_pointer>                 __node;
-    typedef __rebind_alloc<__alloc_traits, __node>                  __node_allocator;
+    typedef __list_node<value_type, __void_pointer>                 __node_type;
+    typedef __rebind_alloc<__alloc_traits, __node_type>             __node_allocator;
     typedef allocator_traits<__node_allocator>                       __node_alloc_traits;
     typedef typename __node_alloc_traits::pointer                    __node_pointer;
     typedef typename __node_alloc_traits::pointer                    __node_const_pointer;
@@ -597,6 +596,23 @@ protected:
         {__move_assign_alloc(__c, integral_constant<bool,
                       __node_alloc_traits::propagate_on_container_move_assignment::value>());}
 
+    template <class ..._Args>
+    _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__link_pointer __prev, __link_pointer __next, _Args&& ...__args) {
+        __node_allocator& __alloc = __node_alloc();
+        __allocation_guard<__node_allocator> __guard(__alloc, 1);
+        __guard.__get()->__prev_ = __prev;
+        __guard.__get()->__next_ = __next;
+        __node_alloc_traits::construct(__alloc, std::addressof(__guard.__get()->__value_), std::forward<_Args>(__args)...);
+        return __guard.__release_ptr();
+    }
+
+    template <class ..._Args>
+    _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) {
+        __node_allocator& __alloc = __node_alloc();
+        __node_alloc_traits::destroy(__alloc, std::addressof(__node->__value_));
+        __node_alloc_traits::deallocate(__alloc, __node, 1);
+    }
+
 private:
     _LIBCPP_INLINE_VISIBILITY
     void __copy_assign_alloc(const __list_imp& __c, true_type)
@@ -670,7 +686,6 @@ __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT
 {
     if (!empty())
     {
-        __node_allocator& __na = __node_alloc();
         __link_pointer __f = __end_.__next_;
         __link_pointer __l = __end_as_link();
         __unlink_nodes(__f, __l->__prev_);
@@ -679,8 +694,7 @@ __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT
         {
             __node_pointer __np = __f->__as_node();
             __f = __f->__next_;
-            __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_));
-            __node_alloc_traits::deallocate(__na, __np, 1);
+            __delete_node(__np);
         }
     }
 }
@@ -718,7 +732,7 @@ class _LIBCPP_TEMPLATE_VIS list
     : private __list_imp<_Tp, _Alloc>
 {
     typedef __list_imp<_Tp, _Alloc> base;
-    typedef typename base::__node              __node;
+    typedef typename base::__node_type         __node_type;
     typedef typename base::__node_allocator    __node_allocator;
     typedef typename base::__node_pointer      __node_pointer;
     typedef typename base::__node_alloc_traits __node_alloc_traits;
@@ -1032,16 +1046,6 @@ public:
 
     _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
 
-    typedef __allocator_destructor<__node_allocator> __node_destructor;
-    typedef unique_ptr<__node, __node_destructor> __hold_pointer;
-
-    _LIBCPP_INLINE_VISIBILITY
-    __hold_pointer __allocate_node(__node_allocator& __na) {
-      __node_pointer __p = __node_alloc_traits::allocate(__na, 1);
-      __p->__prev_ = nullptr;
-      return __hold_pointer(__p, __node_destructor(__na, 1));
-    }
-
 private:
     template <class _Iterator, class _Sentinel>
     _LIBCPP_HIDE_FROM_ABI
@@ -1342,12 +1346,10 @@ template <class _Tp, class _Alloc>
 typename list<_Tp, _Alloc>::iterator
 list<_Tp, _Alloc>::insert(const_iterator __p, const value_type& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
-    __link_nodes(__p.__ptr_, __hold->__as_link(), __hold->__as_link());
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, __x);
+    __link_nodes(__p.__ptr_, __node->__as_link(), __node->__as_link());
     ++base::__sz();
-    return iterator(__hold.release()->__as_link());
+    return iterator(__node->__as_link());
 }
 
 template <class _Tp, class _Alloc>
@@ -1358,12 +1360,9 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _
     if (__n > 0)
     {
         size_type __ds = 0;
-        __node_allocator& __na = base::__node_alloc();
-        __hold_pointer __hold = __allocate_node(__na);
-        __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
+        __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, __x);
         ++__ds;
-        __r = iterator(__hold->__as_link());
-        __hold.release();
+        __r = iterator(__node->__as_link());
         iterator __e = __r;
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         try
@@ -1371,11 +1370,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (--__n; __n != 0; --__n, (void) ++__e, ++__ds)
             {
-                __hold.reset(__node_alloc_traits::allocate(__na, 1));
-                __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
-                __e.__ptr_->__next_ = __hold->__as_link();
-                __hold->__prev_ = __e.__ptr_;
-                __hold.release();
+                __e.__ptr_->__next_ = this->__create_node(/* prev = */__e.__ptr_, /* next = */nullptr, __x)->__as_link();
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1383,9 +1378,9 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _
         {
             while (true)
             {
-                __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e));
                 __link_pointer __prev = __e.__ptr_->__prev_;
-                __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1);
+                __node_pointer __current = __e.__ptr_->__as_node();
+                this->__delete_node(__current);
                 if (__prev == 0)
                     break;
                 __e = iterator(__prev);
@@ -1417,12 +1412,9 @@ list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Se
     if (__f != __l)
     {
         size_type __ds = 0;
-        __node_allocator& __na = base::__node_alloc();
-        __hold_pointer __hold = __allocate_node(__na);
-        __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f);
+        __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, *__f);
         ++__ds;
-        __r = iterator(__hold.get()->__as_link());
-        __hold.release();
+        __r = iterator(__node->__as_link());
         iterator __e = __r;
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         try
@@ -1430,11 +1422,7 @@ list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Se
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (++__f; __f != __l; ++__f, (void) ++__e, ++__ds)
             {
-                __hold.reset(__node_alloc_traits::allocate(__na, 1));
-                __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f);
-                __e.__ptr_->__next_ = __hold.get()->__as_link();
-                __hold->__prev_ = __e.__ptr_;
-                __hold.release();
+                __e.__ptr_->__next_ = this->__create_node(/* prev = */__e.__ptr_, /* next = */nullptr, *__f)->__as_link();
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1442,9 +1430,9 @@ list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Se
         {
             while (true)
             {
-                __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e));
                 __link_pointer __prev = __e.__ptr_->__prev_;
-                __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1);
+                __node_pointer __current = __e.__ptr_->__as_node();
+                this->__delete_node(__current);
                 if (__prev == 0)
                     break;
                 __e = iterator(__prev);
@@ -1462,25 +1450,20 @@ template <class _Tp, class _Alloc>
 void
 list<_Tp, _Alloc>::push_front(const value_type& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
-    __link_pointer __nl = __hold->__as_link();
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, __x);
+    __link_pointer __nl = __node->__as_link();
     __link_nodes_at_front(__nl, __nl);
     ++base::__sz();
-    __hold.release();
 }
 
 template <class _Tp, class _Alloc>
 void
 list<_Tp, _Alloc>::push_back(const value_type& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
-    __link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link());
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, __x);
+    __link_pointer __nl = __node->__as_link();
+    __link_nodes_at_back(__nl, __nl);
     ++base::__sz();
-    __hold.release();
 }
 
 #ifndef _LIBCPP_CXX03_LANG
@@ -1489,24 +1472,20 @@ template <class _Tp, class _Alloc>
 void
 list<_Tp, _Alloc>::push_front(value_type&& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x));
-    __link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link());
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::move(__x));
+    __link_pointer __nl = __node->__as_link();
+    __link_nodes_at_front(__nl, __nl);
     ++base::__sz();
-    __hold.release();
 }
 
 template <class _Tp, class _Alloc>
 void
 list<_Tp, _Alloc>::push_back(value_type&& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x));
-    __link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link());
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::move(__x));
+    __link_pointer __nl = __node->__as_link();
+    __link_nodes_at_back(__nl, __nl);
     ++base::__sz();
-    __hold.release();
 }
 
 template <class _Tp, class _Alloc>
@@ -1518,15 +1497,12 @@ void
 #endif
 list<_Tp, _Alloc>::emplace_front(_Args&&... __args)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...);
-    __link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link());
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::forward<_Args>(__args)...);
+    __link_pointer __nl = __node->__as_link();
+    __link_nodes_at_front(__nl, __nl);
     ++base::__sz();
 #if _LIBCPP_STD_VER >= 17
-    return __hold.release()->__value_;
-#else
-    __hold.release();
+    return __node->__value_;
 #endif
 }
 
@@ -1539,16 +1515,12 @@ void
 #endif
 list<_Tp, _Alloc>::emplace_back(_Args&&... __args)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...);
-    __link_pointer __nl = __hold->__as_link();
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::forward<_Args>(__args)...);
+    __link_pointer __nl = __node->__as_link();
     __link_nodes_at_back(__nl, __nl);
     ++base::__sz();
 #if _LIBCPP_STD_VER >= 17
-    return __hold.release()->__value_;
-#else
-    __hold.release();
+    return __node->__value_;
 #endif
 }
 
@@ -1557,13 +1529,10 @@ template <class... _Args>
 typename list<_Tp, _Alloc>::iterator
 list<_Tp, _Alloc>::emplace(const_iterator __p, _Args&&... __args)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...);
-    __link_pointer __nl = __hold.get()->__as_link();
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::forward<_Args>(__args)...);
+    __link_pointer __nl = __node->__as_link();
     __link_nodes(__p.__ptr_, __nl, __nl);
     ++base::__sz();
-    __hold.release();
     return iterator(__nl);
 }
 
@@ -1571,13 +1540,10 @@ template <class _Tp, class _Alloc>
 typename list<_Tp, _Alloc>::iterator
 list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x)
 {
-    __node_allocator& __na = base::__node_alloc();
-    __hold_pointer __hold = __allocate_node(__na);
-    __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x));
-    __link_pointer __nl = __hold->__as_link();
+    __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, std::move(__x));
+    __link_pointer __nl = __node->__as_link();
     __link_nodes(__p.__ptr_, __nl, __nl);
     ++base::__sz();
-    __hold.release();
     return iterator(__nl);
 }
 
@@ -1588,13 +1554,10 @@ void
 list<_Tp, _Alloc>::pop_front()
 {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_front() called with empty list");
-    __node_allocator& __na = base::__node_alloc();
     __link_pointer __n = base::__end_.__next_;
     base::__unlink_nodes(__n, __n);
     --base::__sz();
-    __node_pointer __np = __n->__as_node();
-    __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_));
-    __node_alloc_traits::deallocate(__na, __np, 1);
+    this->__delete_node(__n->__as_node());
 }
 
 template <class _Tp, class _Alloc>
@@ -1602,13 +1565,10 @@ void
 list<_Tp, _Alloc>::pop_back()
 {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_back() called on an empty list");
-    __node_allocator& __na = base::__node_alloc();
     __link_pointer __n = base::__end_.__prev_;
     base::__unlink_nodes(__n, __n);
     --base::__sz();
-    __node_pointer __np = __n->__as_node();
-    __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_));
-    __node_alloc_traits::deallocate(__na, __np, 1);
+    this->__delete_node(__n->__as_node());
 }
 
 template <class _Tp, class _Alloc>
@@ -1617,14 +1577,11 @@ list<_Tp, _Alloc>::erase(const_iterator __p)
 {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(),
         "list::erase(iterator) called with a non-dereferenceable iterator");
-    __node_allocator& __na = base::__node_alloc();
     __link_pointer __n = __p.__ptr_;
     __link_pointer __r = __n->__next_;
     base::__unlink_nodes(__n, __n);
     --base::__sz();
-    __node_pointer __np = __n->__as_node();
-    __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_));
-    __node_alloc_traits::deallocate(__na, __np, 1);
+    this->__delete_node(__n->__as_node());
     return iterator(__r);
 }
 
@@ -1634,16 +1591,13 @@ list<_Tp, _Alloc>::erase(const_iterator __f, const_iterator __l)
 {
     if (__f != __l)
     {
-        __node_allocator& __na = base::__node_alloc();
         base::__unlink_nodes(__f.__ptr_, __l.__ptr_->__prev_);
         while (__f != __l)
         {
             __link_pointer __n = __f.__ptr_;
             ++__f;
             --base::__sz();
-            __node_pointer __np = __n->__as_node();
-            __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_));
-            __node_alloc_traits::deallocate(__na, __np, 1);
+            this->__delete_node(__n->__as_node());
         }
     }
     return iterator(__l.__ptr_);
@@ -1659,11 +1613,9 @@ list<_Tp, _Alloc>::resize(size_type __n)
     {
         __n -= base::__sz();
         size_type __ds = 0;
-        __node_allocator& __na = base::__node_alloc();
-        __hold_pointer __hold = __allocate_node(__na);
-        __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_));
+        __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr);
         ++__ds;
-        iterator __r = iterator(__hold.release()->__as_link());
+        iterator __r = iterator(__node->__as_link());
         iterator __e = __r;
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         try
@@ -1671,11 +1623,7 @@ list<_Tp, _Alloc>::resize(size_type __n)
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (--__n; __n != 0; --__n, (void) ++__e, ++__ds)
             {
-                __hold.reset(__node_alloc_traits::allocate(__na, 1));
-                __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_));
-                __e.__ptr_->__next_ = __hold.get()->__as_link();
-                __hold->__prev_ = __e.__ptr_;
-                __hold.release();
+                __e.__ptr_->__next_ = this->__create_node(/* prev = */__e.__ptr_, /* next = */nullptr)->__as_link();
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1683,9 +1631,9 @@ list<_Tp, _Alloc>::resize(size_type __n)
         {
             while (true)
             {
-                __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e));
                 __link_pointer __prev = __e.__ptr_->__prev_;
-                __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1);
+                __node_pointer __current = __e.__ptr_->__as_node();
+                this->__delete_node(__current);
                 if (__prev == 0)
                     break;
                 __e = iterator(__prev);
@@ -1708,11 +1656,9 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x)
     {
         __n -= base::__sz();
         size_type __ds = 0;
-        __node_allocator& __na = base::__node_alloc();
-        __hold_pointer __hold = __allocate_node(__na);
-        __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
+        __node_pointer __node = this->__create_node(/* prev = */nullptr, /* next = */nullptr, __x);
         ++__ds;
-        __link_pointer __nl = __hold.release()->__as_link();
+        __link_pointer __nl = __node->__as_link();
         iterator __r = iterator(__nl);
         iterator __e = __r;
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
@@ -1721,11 +1667,7 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x)
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
             for (--__n; __n != 0; --__n, (void) ++__e, ++__ds)
             {
-                __hold.reset(__node_alloc_traits::allocate(__na, 1));
-                __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x);
-                __e.__ptr_->__next_ = __hold.get()->__as_link();
-                __hold->__prev_ = __e.__ptr_;
-                __hold.release();
+                __e.__ptr_->__next_ = this->__create_node(/* prev = */__e.__ptr_, /* next = */nullptr, __x)->__as_link();
             }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
@@ -1733,9 +1675,9 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x)
         {
             while (true)
             {
-                __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e));
                 __link_pointer __prev = __e.__ptr_->__prev_;
-                __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1);
+                __node_pointer __current = __e.__ptr_->__as_node();
+                this->__delete_node(__current);
                 if (__prev == 0)
                     break;
                 __e = iterator(__prev);
@@ -2124,6 +2066,7 @@ _LIBCPP_POP_MACROS
 #  include <algorithm>
 #  include <atomic>
 #  include <concepts>
+#  include <cstdint>
 #  include <cstdlib>
 #  include <functional>
 #  include <iosfwd>
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index b77ffa499f8cca3..37095662bc30bc7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -230,8 +230,6 @@ format tuple
 format version
 forward_list compare
 forward_list cstddef
-forward_list cstdint
-forward_list cstring
 forward_list initializer_list
 forward_list limits
 forward_list new
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index b77ffa499f8cca3..37095662bc30bc7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -230,8 +230,6 @@ format tuple
 format version
 forward_list compare
 forward_list cstddef
-forward_list cstdint
-forward_list cstring
 forward_list initializer_list
 forward_list limits
 forward_list new



More information about the libcxx-commits mailing list