diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -502,6 +502,7 @@ __memory/temp_value.h __memory/temporary_buffer.h __memory/uninitialized_algorithms.h + __memory/uninitialized_buffer.h __memory/unique_ptr.h __memory/uses_allocator.h __memory/uses_allocator_construction.h diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -24,7 +24,7 @@ #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__memory/destruct_n.h> -#include <__memory/temporary_buffer.h> +#include <__memory/uninitialized_buffer.h> #include <__memory/unique_ptr.h> #include <__utility/pair.h> #include @@ -225,13 +225,16 @@ difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); difference_type __buf_size = _VSTD::min(__len1, __len2); -// TODO: Remove the use of std::get_temporary_buffer -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - pair __buf = _VSTD::get_temporary_buffer(__buf_size); -_LIBCPP_SUPPRESS_DEPRECATED_POP - unique_ptr __h(__buf.first); + auto __buf = std::__make_uninitialized_buffer(nothrow, __buf_size); return std::__inplace_merge<_AlgPolicy>( - std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second); + std::move(__first), + std::move(__middle), + std::move(__last), + __comp, + __len1, + __len2, + __buf.get(), + __buf ? __buf_size : 0); } template diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h --- a/libcxx/include/__algorithm/stable_partition.h +++ b/libcxx/include/__algorithm/stable_partition.h @@ -16,7 +16,7 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__memory/destruct_n.h> -#include <__memory/temporary_buffer.h> +#include <__memory/uninitialized_buffer.h> #include <__memory/unique_ptr.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator +_LIBCPP_HIDDEN _ForwardIterator __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, _Distance __len, _Pair __p, forward_iterator_tag __fit) { @@ -138,18 +138,18 @@ // We now have a reduced range [__first, __last) // *__first is known to be false difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); - pair __p(0, 0); - unique_ptr __h; + + __uninitialized_buffer_t __buf; if (__len >= __alloc_limit) - { -// TODO: Remove the use of std::get_temporary_buffer -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - __p = _VSTD::get_temporary_buffer(__len); -_LIBCPP_SUPPRESS_DEPRECATED_POP - __h.reset(__p.first); - } + __buf = std::__make_uninitialized_buffer(nothrow, __len); + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( - std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag()); + std::move(__first), + std::move(__last), + __pred, + __len, + std::make_pair(__buf.get(), __buf ? __len : 0), + forward_iterator_tag()); } template @@ -292,18 +292,17 @@ // *__last is known to be true // __len >= 2 difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1; - pair __p(0, 0); - unique_ptr __h; + __uninitialized_buffer_t __buf; if (__len >= __alloc_limit) - { -// TODO: Remove the use of std::get_temporary_buffer -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - __p = _VSTD::get_temporary_buffer(__len); -_LIBCPP_SUPPRESS_DEPRECATED_POP - __h.reset(__p.first); - } + __buf = std::__make_uninitialized_buffer(nothrow, __len); + return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( - std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag()); + std::move(__first), + std::move(__last), + __pred, + __len, + std::make_pair(__buf.get(), __buf ? __len : 0), + bidirectional_iterator_tag()); } template diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -18,7 +18,7 @@ #include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> #include <__memory/destruct_n.h> -#include <__memory/temporary_buffer.h> +#include <__memory/uninitialized_buffer.h> #include <__memory/unique_ptr.h> #include <__type_traits/is_trivially_copy_assignable.h> #include <__utility/move.h> @@ -249,17 +249,12 @@ using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; difference_type __len = __last - __first; - pair __buf(0, 0); - unique_ptr __h; - if (__len > static_cast(__stable_sort_switch::value)) { -// TODO: Remove the use of std::get_temporary_buffer -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - __buf = std::get_temporary_buffer(__len); -_LIBCPP_SUPPRESS_DEPRECATED_POP - __h.reset(__buf.first); - } + __uninitialized_buffer_t __buf; + if (__len > static_cast(__stable_sort_switch::value)) + __buf = std::__make_uninitialized_buffer(nothrow, __len); - std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second); + std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >( + __first, __last, __comp, __len, __buf.get(), __buf ? __len : 0); std::__check_strict_weak_ordering_sorted(__first, __last, __comp); } diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -93,6 +93,16 @@ return __last; } +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_ForwardIterator __destroy_n(_ForwardIterator __first, _Size __n) { + while (__n > 0) { + std::__destroy_at(std::addressof(*__first)); + ++__first; + --__n; + } + return __first; +} #if _LIBCPP_STD_VER >= 17 template , int> = 0> @@ -118,9 +128,7 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { - for (; __n > 0; (void)++__first, --__n) - std::__destroy_at(std::addressof(*__first)); - return __first; + return std::__destroy_n(__first, __n); } #endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/__memory/temporary_buffer.h b/libcxx/include/__memory/temporary_buffer.h --- a/libcxx/include/__memory/temporary_buffer.h +++ b/libcxx/include/__memory/temporary_buffer.h @@ -74,14 +74,6 @@ _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); } -struct __return_temporary_buffer -{ -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - template - _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) const {_VSTD::return_temporary_buffer(__p);} -_LIBCPP_SUPPRESS_DEPRECATED_POP -}; - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MEMORY_TEMPORARY_BUFFER_H diff --git a/libcxx/include/__memory/uninitialized_buffer.h b/libcxx/include/__memory/uninitialized_buffer.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__memory/uninitialized_buffer.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_UNINITIALIZED_BUFFER_H +#define _LIBCPP___MEMORY_UNINITIALIZED_BUFFER_H + +#include <__config> +#include <__memory/construct_at.h> +#include <__memory/unique_ptr.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/remove_extent.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// __make_uninitialized_buffer is a utility function to allocate some memory for scratch storage. The __destructor is +// called before deleting the memory, making it possible to destroy any leftover elements. The __destructor is called +// with the pointer to the first element and the total number of elements. + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class __uninitialized_buffer_deleter { + size_t __count_; + _Destructor __destructor_; + +public: + template ::value, _Dummy> = 0> + __uninitialized_buffer_deleter() : __count_(0) {} + + __uninitialized_buffer_deleter(size_t __count, _Destructor __destructor) + : __count_(__count), __destructor_(std::move(__destructor)) {} + + template + _LIBCPP_HIDE_FROM_ABI void operator()(_Tp* __ptr) { + __destructor_(__ptr, __count_); +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + ::operator delete(__ptr); +#else + ::operator delete(__ptr, __count_ * sizeof(_Tp), align_val_t(_LIBCPP_ALIGNOF(_Tp))); +#endif + } +}; + +struct __noop { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()(_Args&&...) const {} +}; + +template +using __uninitialized_buffer_t = unique_ptr<_Array, __uninitialized_buffer_deleter<_Destructor> >; + +template +_LIBCPP_HIDE_FROM_ABI __uninitialized_buffer_t<_Array, _Destructor> +__make_uninitialized_buffer(nothrow_t, size_t __count, _Destructor __destructor = __noop()) { + static_assert(is_array<_Array>::value, ""); + using _Tp = __remove_extent_t<_Array>; + +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + _Tp* __ptr = static_cast<_Tp*>(::operator new(sizeof(_Tp) * __count, nothrow)); +#else + _Tp* __ptr = static_cast<_Tp*>(::operator new(sizeof(_Tp) * __count, align_val_t(_LIBCPP_ALIGNOF(_Tp)), nothrow)); +#endif + + using _Deleter = __uninitialized_buffer_deleter<_Destructor>; + return unique_ptr<_Array, _Deleter>(__ptr, _Deleter(__count, std::move(__destructor))); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_UNINITIALIZED_BUFFER_H diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1211,6 +1211,7 @@ module temp_value { private header "__memory/temp_value.h" } module temporary_buffer { private header "__memory/temporary_buffer.h" } module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } + module uninitialized_buffer { private header "__memory/uninitialized_buffer.h" } module unique_ptr { private header "__memory/unique_ptr.h" } module uses_allocator { private header "__memory/uses_allocator.h" } module uses_allocator_construction { private header "__memory/uses_allocator_construction.h" } diff --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h --- a/libcxx/test/support/count_new.h +++ b/libcxx/test/support/count_new.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include