[libcxx-commits] [libcxx] [libc++] Add __uninitialized_allocator_{fill, value_construct, move} and use them in vector (PR #207500)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jul 6 00:26:33 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/207500
>From 70975eb30423b4b3ac4e4d60596d009668067650 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 4 Jul 2026 11:06:55 +0200
Subject: [PATCH] [libc++] Add
__uninitialized_allocator_{fill,value_construct,move} and use them in vector
---
.../__memory/uninitialized_algorithms.h | 38 +++++++++++++++++++
libcxx/include/__vector/vector.h | 14 ++-----
.../sequences/vector/asan_throw.pass.cpp | 2 +-
3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index 45c8b71459eef..5426dae7ef114 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -450,6 +450,30 @@ __uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _B
#endif // _LIBCPP_STD_VER >= 17
+template <class _Alloc, class _Iter, class _Sent, class _Tp>
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+_Iter __uninitialized_allocator_fill(_Alloc& __alloc, _Iter __first, _Sent __last, const _Tp& __value) {
+ auto __iter = __first;
+
+ auto __guard = std::__make_exception_guard([&] { std::__allocator_destroy(__alloc, __first, __iter); });
+ for (; __iter != __last; ++__iter)
+ allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__iter), __value);
+ __guard.__complete();
+ return __iter;
+}
+
+template <class _Alloc, class _Iter, class _Sent>
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+_Iter __uninitialized_allocator_value_construct(_Alloc& __alloc, _Iter __first, _Sent __last) {
+ auto __iter = __first;
+
+ auto __guard = std::__make_exception_guard([&] { std::__allocator_destroy(__alloc, __first, __iter); });
+ for (; __iter != __last; ++__iter)
+ allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__iter));
+ __guard.__complete();
+ return __iter;
+}
+
template <class _Alloc, class _Iter>
class _AllocatorDestroyRangeReverse {
public:
@@ -528,6 +552,20 @@ inline const bool __allocator_has_trivial_move_construct_v = !__has_construct_v<
template <class _Type>
inline const bool __allocator_has_trivial_move_construct_v<allocator<_Type>, _Type> = true;
+template <class _Alloc, class _InIter, class _Sent, class _OutIter>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __in_out_result<_InIter, _OutIter>
+__uninitialized_allocator_move(_Alloc& __alloc, _InIter __first, _Sent __last, _OutIter __result) {
+ auto __destruct_first = __result;
+ auto __guard = std::__make_exception_guard([&] { std::__allocator_destroy(__alloc, __destruct_first, __result); });
+ while (__first != __last) {
+ allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move(*__first));
+ ++__first;
+ ++__result;
+ }
+ __guard.__complete();
+ return {std::move(__first), std::move(__result)};
+}
+
template <class _Alloc, class _Tp>
inline const bool __allocator_has_trivial_destroy_v = !__has_destroy_v<_Alloc, _Tp*>;
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 2b9508ecafeac..603b5676e05fb 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -880,10 +880,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) {
_ConstructTransaction __tx(*this, __n);
- const_pointer __new_end = __tx.__new_end_;
- for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos));
- }
+ __tx.__pos_ = std::__uninitialized_allocator_value_construct(__layout_.__alloc(), __tx.__pos_, __tx.__new_end_);
}
// Copy constructs __n objects starting at __layout_.__end_ptr() from __x
@@ -896,10 +893,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
_ConstructTransaction __tx(*this, __n);
- const_pointer __new_end = __tx.__new_end_;
- for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), __x);
- }
+ __tx.__pos_ = std::__uninitialized_allocator_fill(__layout_.__alloc(), __tx.__pos_, __tx.__new_end_, __x);
}
template <class _Tp, class _Allocator>
@@ -1123,9 +1117,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
{
pointer __i = __from_s + __n;
_ConstructTransaction __tx(*this, __from_e - __i);
- for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
- __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), std::move(*__i));
- }
+ __tx.__pos_ = std::__uninitialized_allocator_move(__layout_.__alloc(), __i, __from_e, __tx.__pos_).__out_;
}
std::move_backward(__from_s, __from_s + __n, __old_last);
}
diff --git a/libcxx/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp
index dcfa8029cfc0d..5089cd716266a 100644
--- a/libcxx/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp
+++ b/libcxx/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp
@@ -182,7 +182,7 @@ void test_insert_n2() {
v.insert(v.cbegin(), 5, ThrowOnCopy());
assert(0);
} catch (int e) {
- assert(v.size() == 11);
+ assert(v.size() == 10);
assert(is_contiguous_container_asan_correct(v));
return;
}
More information about the libcxx-commits
mailing list