diff --git a/libcxx/include/__memory/allocation_guard.h b/libcxx/include/__memory/allocation_guard.h --- a/libcxx/include/__memory/allocation_guard.h +++ b/libcxx/include/__memory/allocation_guard.h @@ -55,9 +55,29 @@ _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { - if (__ptr_ != nullptr) { - allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + __destroy(); + } + + _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete; + _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT + : __alloc_(std::move(__other.__alloc)) + , __n_(__other.__n) + , __ptr_(__other.__ptr_) { + __other.__ptr_ = nullptr; + } + + _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(const __allocation_guard& __other) = delete; + _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(__allocation_guard&& __other) _NOEXCEPT { + if (&__other != this) { + __destroy(); + + __alloc_ = std::move(__other.__alloc_); + __n_ = __other.__n_; + __ptr_ = __other.__ptr_; + __other.__ptr_ = nullptr; } + + return *this; } _LIBCPP_HIDE_FROM_ABI @@ -73,6 +93,13 @@ } private: + _LIBCPP_HIDE_FROM_ABI + void __destroy() _NOEXCEPT { + if (__ptr_ != nullptr) { + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + } + } + _Alloc __alloc_; _Size __n_; _Pointer __ptr_; diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -194,6 +194,7 @@ #include <__iterator/move_iterator.h> #include <__iterator/next.h> #include <__memory/addressof.h> +#include <__memory/allocation_guard.h> #include <__memory/allocator.h> #include <__memory/allocator_destructor.h> #include <__memory/allocator_traits.h> @@ -291,6 +292,7 @@ pointer __next_; _LIBCPP_INLINE_VISIBILITY __forward_begin_node() : __next_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY explicit __forward_begin_node(pointer __n) : __next_(__n) {} _LIBCPP_INLINE_VISIBILITY __begin_node_pointer __next_as_begin() const { @@ -306,8 +308,13 @@ : public __begin_node_of<_Tp, _VoidPtr> { typedef _Tp value_type; + typedef __begin_node_of<_Tp, _VoidPtr> _Base; + typedef typename _Base::pointer _NodePtr; value_type __value_; + + _LIBCPP_HIDE_FROM_ABI __forward_list_node() = default; + _LIBCPP_HIDE_FROM_ABI __forward_list_node(const value_type& __v, _NodePtr __next) : _Base(__next), __value_(__v) {} }; @@ -1246,14 +1253,15 @@ 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(); - 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); - __node_pointer __first = __h.release(); + _Guard __h(__a, 1); + std::__construct_at(std::addressof(*__h.__get()), __v, /*__next_ =*/nullptr); + __node_pointer __first = __h.__release_ptr(); __node_pointer __last = __first; #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try @@ -1261,9 +1269,9 @@ #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (--__n; __n != 0; --__n, __last = __last->__next_) { - __h.reset(__node_traits::allocate(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); - __last->__next_ = __h.release(); + __h = _Guard(__a, 1); + std::__construct_at(std::addressof(*__h.__get()), __v, /*__next_ =*/nullptr); + __last->__next_ = __h.__release_ptr(); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } @@ -1292,14 +1300,15 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l) { + using _Guard = __allocation_guard<__node_allocator>; + __begin_node_pointer __r = __p.__get_begin(); if (__f != __l) { __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_), *__f); - __node_pointer __first = __h.release(); + _Guard __h(__a, 1); + std::__construct_at(std::addressof(*__h.__get()), *__f, /*__next_ =*/nullptr); + __node_pointer __first = __h.__release_ptr(); __node_pointer __last = __first; #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try @@ -1307,9 +1316,9 @@ #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_))) { - __h.reset(__node_traits::allocate(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), *__f); - __last->__next_ = __h.release(); + __h = _Guard(__a, 1); + std::__construct_at(std::addressof(*__h.__get()), *__f, /*__next_ =*/nullptr); + __last->__next_ = __h.__release_ptr(); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } diff --git a/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h b/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h --- a/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h +++ b/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h @@ -17,6 +17,7 @@ #include #include +#include "../exception_safety_helpers.h" #include "../from_range_helpers.h" #include "MoveOnly.h" #include "almost_satisfies_types.h" @@ -192,18 +193,11 @@ template