[libcxx-commits] [libcxx] [libcxx] adds a size-based representation for `vector`'s unstable ABI (PR #155330)
Christopher Di Bella via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Mar 21 13:11:25 PDT 2026
https://github.com/cjdb updated https://github.com/llvm/llvm-project/pull/155330
>From ba94eeba1e22ebee9708c770c3b7da73eaad131e Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 25 Aug 2025 23:06:45 +0000
Subject: [PATCH 01/39] [libcxx] adds a size-based representation for
`vector`'s unstable ABI
**tl;dr** We can significantly improve the runtime performance of
`std::vector` by changing its representation from three pointers to one
pointer and two integers. This document explains the details of this
change, along with the justifications for making it. See the [RFC] for
more information.
This commit changes `std::vector`'s representation in a similar manner
to `__split_buffer` in #139632. We introduce a layout type that tracks
implementation details that differ between the pointer-based vector
and size-based vector representations. `vector` does not parameterise
its layout type, unlike `__split_buffer`. `__split_buffer` is used by
both `vector` and `deque`, and being able to take an ABI break on
`vector` doesn't automatically mean that users can also tolerate a break
on `deque`. The most convenient way to work around this problem is to
parameterise the layout type. Users of `std::vector` should not depend
on its layout, and libc++ has no internal reason to toggle it, so we
keep the representation concrete.
To use this feature, you'll need to configure libc++ so that it's built
with `-DLIBCXX_UNSTABLE_ABI=Yes`.
[RFC]: https://discourse.llvm.org/t/adding-a-size-based-vector-to-libc-s-unstable-abi/86306
---
libcxx/include/__configuration/abi.h | 1 +
libcxx/include/__split_buffer | 8 +-
libcxx/include/__vector/vector.h | 800 ++++++++++++------
.../alg.swap/ranges.swap_ranges.pass.cpp | 54 +-
libcxx/utils/gdb/libcxx/printers.py | 18 +-
5 files changed, 597 insertions(+), 284 deletions(-)
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 38b85c6ac70de..70aef42b487ac 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -79,6 +79,7 @@
# define _LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
+# define _LIBCPP_ABI_SIZE_BASED_VECTOR
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1e05e4df8ba0f..9a55f855bbfda 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -268,7 +268,6 @@ public:
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
// Size-based __split_buffers track their size directly: we need to explicitly update the size
// when the front is adjusted.
- __size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
__set_sentinel(__new_end);
}
@@ -277,7 +276,6 @@ public:
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
// Size-based __split_buffers track their size directly: we need to explicitly update the size
// when the front is adjusted.
- __size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
__set_sentinel(__new_size);
}
@@ -316,9 +314,9 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
- __split_buffer_pointer_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_pointer_layout>,
- value_type,
- __alloc_rr&>& __other) _NOEXCEPT {
+ __split_buffer_size_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_size_layout>,
+ value_type,
+ __alloc_rr&>& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 7051e044314ea..9e94fe75123eb 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -55,6 +55,7 @@
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_pointer.h>
#include <__type_traits/is_same.h>
+#include <__type_traits/is_swappable.h>
#include <__type_traits/is_trivially_relocatable.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
@@ -82,25 +83,334 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template <class _Vector, class _Tp, class _Allocator>
+class __vector_layout {
+public:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
+ using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator&, __split_buffer_size_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+
+ _LIBCPP_HIDE_FROM_ABI __vector_layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
+ _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __alloc_(__a) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __alloc_(std::move(__a)) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_)),
+ __size_(std::move(__other.__size_)),
+ __cap_(std::move(__other.__cap_)),
+ __alloc_(std::move(__other.__alloc_)) {
+ __other.__begin_ = nullptr;
+ __other.__size_ = 0;
+ __other.__cap_ = 0;
+ }
+
+ // Capacity
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return __size_;
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __size_ == 0;
+ }
+
+ // Access
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
+ return __alloc_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
+ __allocator_ref() const _NOEXCEPT {
+ return __alloc_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __x.__begin_);
+ std::swap(__size_, __x.__size_);
+ std::swap(__cap_, __x.__cap_);
+ std::__swap_allocator(__alloc_, __x.__alloc_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
+ return __begin_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ return __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __size_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __end - __begin_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __size_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ __cap_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ || __cap_)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+
+private:
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
+};
+#else
+template <class _Vector, class _Tp, class _Allocator>
+class __vector_layout {
+public:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
+ using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator&, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
+
+ // Can't be defaulted due to _LIBCPP_COMPRESSED_PAIR not being an aggregate in C++03 and C++11.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __cap_(nullptr) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
+ _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __cap_(nullptr), __alloc_(__a) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __cap_(nullptr), __alloc_(std::move(__a)) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_)),
+ __end_(std::move(__other.__end_)),
+ __cap_(std::move(__other.__cap_)),
+ __alloc_(std::move(__other.__alloc_)) {
+ __other.__begin_ = nullptr;
+ __other.__end_ = nullptr;
+ __other.__cap_ = nullptr;
+ }
+
+ // Capacity
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __begin_ == __end_;
+ }
+
+ // Access
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
+ return __alloc_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
+ __allocator_ref() const _NOEXCEPT {
+ return __alloc_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __x.__begin_);
+ std::swap(__end_, __x.__end_);
+ std::swap(__cap_, __x.__cap_);
+ std::__swap_allocator(__alloc_, __x.__alloc_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
+ return __begin_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __end_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __begin_ + __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
+ __end_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+
+private:
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
+};
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector {
- template <class _Up, class _Alloc>
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Up, _Alloc, __split_buffer_pointer_layout>;
+class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
+ using __base _LIBCPP_NODEBUG = __vector_layout<vector, _Tp, _Allocator>;
+ using __self _LIBCPP_NODEBUG = vector;
+ using __base::__allocator_ref;
+ using __base::__end_pointer;
+ using __base::__is_full;
+ using __base::__raw_begin;
+ using __base::__raw_capacity;
+ using __base::__raw_sentinel;
+ using __base::__remaining_capacity;
+ using __base::__set_capacity;
+ using __base::__set_sentinel;
+ using __base::__set_valid_range;
+ using typename __base::__alloc_traits;
+ using typename __base::__sentinel_type;
+ using typename __base::__split_buffer;
public:
- //
- // Types
- //
- using __self _LIBCPP_NODEBUG = vector;
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using reference = typename __base::reference;
+ using const_reference = typename __base::const_reference;
+ using size_type = typename __base::size_type;
+ using difference_type = typename __base::difference_type;
+ using pointer = typename __base::pointer;
+ using const_pointer = typename __base::const_pointer;
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
// Users might provide custom allocators, and prior to C++20 we have no existing way to detect whether the allocator's
// pointer type is contiguous (though it has to be by the Standard). Using the wrapper type ensures the iterator is
@@ -114,6 +424,8 @@ class vector {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using __base::__invariants;
+
// A vector containers the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
// - allocator_type: may be trivially relocatable, so it's checked
@@ -138,7 +450,7 @@ class vector {
#else
noexcept
#endif
- : __alloc_(__a) {
+ : __base(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -152,7 +464,7 @@ class vector {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -174,7 +486,7 @@ class vector {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -197,7 +509,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
__init_with_sentinel(__first, __last);
}
@@ -218,7 +530,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -227,7 +539,7 @@ class vector {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __alloc_(__alloc) {
+ : __base(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -244,10 +556,10 @@ class vector {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__begin_ != nullptr) {
+ if (__vec_.__raw_begin() != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__allocator_ref(), __vec_.__raw_begin(), __vec_.capacity());
}
}
@@ -259,13 +571,13 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) {
- __init_with_size(__x.__begin_, __x.__end_, __x.size());
+ : __base(__alloc_traits::select_on_container_copy_construction(__x.__allocator_ref())) {
+ __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- __init_with_size(__x.__begin_, __x.__end_, __x.size());
+ : __base(__a) {
+ __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -276,7 +588,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -339,23 +651,23 @@ class vector {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return this->__alloc_;
+ return __allocator_ref();
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(__raw_begin()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(__raw_begin()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__end_));
+ return __make_iter(__add_alignment_assumption(__end_pointer()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__end_));
+ return __make_iter(__add_alignment_assumption(__end_pointer()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
@@ -389,17 +701,19 @@ class vector {
//
// [vector.capacity], capacity
//
+
+ // Capacity
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(this->__end_ - this->__begin_);
+ return __base::size();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(this->__cap_ - this->__begin_);
+ return __base::capacity();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return this->__begin_ == this->__end_;
+ return __base::empty();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__allocator_ref()), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -409,50 +723,48 @@ class vector {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *__raw_begin();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *__raw_begin();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base::back();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base::back();
}
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(__raw_begin());
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(__raw_begin());
}
//
@@ -477,7 +789,7 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -490,7 +802,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
- this->__destruct_at_end(this->__end_ - 1);
+ this->__destruct_at_end(__end_pointer() - 1);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x);
@@ -546,41 +858,39 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(this->__begin_);
+ __base_destruct_at_end(__raw_begin());
__annotate_shrink(__old_size);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector& __other)
#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT;
+ _NOEXCEPT
#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
#endif
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+ {
+ __base::swap(__other);
+ }
private:
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
- // Precondition: __begin_ == __end_ == __cap_ == nullptr
+ // Precondition: begin() == nullptr
+ // Precondition: size() == 0
+ // Precondition: capacity() == 0
// Precondition: __n > 0
// Postcondition: capacity() >= __n
// Postcondition: size() == 0
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(this->__alloc_, __n);
- __begin_ = __allocation.ptr;
- __end_ = __allocation.ptr;
- __cap_ = __begin_ + __allocation.count;
+ auto __allocation = std::__allocate_at_least(__allocator_ref(), __n);
+ __set_valid_range(__allocation.ptr, static_cast<size_type>(0));
+ __set_capacity(__allocation.count);
__annotate_new(0);
}
@@ -628,7 +938,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, *__first);
+ __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), *__first);
*__position = std::move(__tmp.get());
}
}
@@ -672,8 +982,8 @@ class vector {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(this->__begin_),
- std::__wrap_iter<pointer>(this->__cap_));
+ std::__wrap_iter<pointer>(__raw_begin()),
+ std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -684,17 +994,16 @@ class vector {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(this->__begin_),
- std::__wrap_iter<const_pointer>(this->__cap_));
+ std::__wrap_iter<const_pointer>(__raw_begin()),
+ std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p);
+ __swap_out_circular_buffer(__split_buffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -708,7 +1017,7 @@ class vector {
}
template <class... _Args>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline pointer __emplace_back_slow_path(_Args&&... __args);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __emplace_back_slow_path(_Args&&... __args);
// The following functions are no-ops outside of AddressSanitizer mode.
// We call annotations for every allocator, unless explicitly disabled.
@@ -741,14 +1050,14 @@ class vector {
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
- : __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) {
+ : __v_(__v), __pos_(__v.__end_pointer()), __new_end_(__pos_ + __n) {
__v_.__annotate_increase(__n);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __v_.__end_ = __pos_;
+ __v_.__set_sentinel(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__begin_);
+ __v_.__annotate_shrink(__new_end_ - __v_.__raw_begin());
}
}
@@ -761,10 +1070,10 @@ class vector {
};
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
- pointer __soon_to_be_end = this->__end_;
+ pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end));
- this->__end_ = __new_last;
+ __alloc_traits::destroy(__allocator_ref(), std::__to_address(--__soon_to_be_end));
+ __set_sentinel(__new_last);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {
@@ -782,20 +1091,21 @@ class vector {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (__allocator_ref() != __c.__allocator_ref()) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
- this->__begin_ = this->__end_ = this->__cap_ = nullptr;
+ __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __set_valid_range(nullptr, static_cast<size_type>(0));
+ __set_capacity(static_cast<__sentinel_type>(0));
}
- this->__alloc_ = __c.__alloc_;
+ __allocator_ref() = __c.__allocator_ref();
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- this->__alloc_ = std::move(__c.__alloc_);
+ __allocator_ref() = std::move(__c.__allocator_ref());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -815,19 +1125,17 @@ class vector {
return __p;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer<_Tp, allocator_type&>& __sb) {
- auto __vector_begin = __begin_;
- auto __vector_sentinel = __end_;
- auto __vector_cap = __cap_;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer& __sb) {
+ auto __vector_begin = __raw_begin();
+ auto __vector_sentinel = __raw_sentinel();
+ auto __vector_cap = __raw_capacity();
auto __sb_begin = __sb.begin();
auto __sb_sentinel = __sb.__raw_sentinel();
auto __sb_cap = __sb.__raw_capacity();
- // TODO: replace with __set_valid_range and __set_capacity when vector supports it.
- __begin_ = __sb_begin;
- __end_ = __sb_sentinel;
- __cap_ = __sb_cap;
+ __set_valid_range(__sb_begin, __sb_sentinel);
+ __set_capacity(__sb_cap);
__sb.__set_valid_range(__vector_begin, __vector_sentinel);
__sb.__set_capacity(__vector_cap);
@@ -855,47 +1163,53 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__begin_, __end_) into the front of __v and swaps the buffers of
-// *this and __v. It is assumed that __v provides space for exactly (__end_ - __begin_) objects in the front. This
+// __swap_out_circular_buffer relocates the objects in [__raw_begin(), size()) into the front of __v and swaps the
+// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_), std::__to_address(__new_begin));
+ __allocator_ref(),
+ std::__to_address(__raw_begin()),
+ std::__to_address(__end_pointer()),
+ std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
- __end_ = __begin_; // All the objects have been destroyed by relocating them.
+ __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ // __v.__size_ += __size_;
__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
-// [__p, __end_) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __begin_) objects in the front and space for at least (__end_ - __p) objects in the back. This
-// function has a strong exception guarantee if __begin_ == __p || __end_ == __p.
+// __swap_out_circular_buffer relocates the objects in [__raw_begin(), __p) into the front of __v, the objects in
+// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
+// exactly (__p - __raw_begin()) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __raw_begin() == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
- // Relocate [__p, __end_) first to avoid having a hole in [__begin_, __end_)
- // in case something in [__begin_, __p) throws.
+ pointer __end = __end_pointer();
+ // Relocate [__p, __end) first to avoid having a hole in [__raw_begin(), __end)
+ // in case something in [__raw_begin(), __p) throws.
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.end()));
- auto __relocated_so_far = __end_ - __p;
+ __allocator_ref(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
- __end_ = __p; // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __begin_);
+ __set_sentinel(
+ __raw_sentinel() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
+ auto __new_begin = __v.begin() - (__p - __raw_begin());
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__set_valid_range(__new_begin, __v.end());
- __end_ = __begin_; // All the objects have been destroyed by relocating them.
+ __allocator_ref(), std::__to_address(__raw_begin()), std::__to_address(__p), std::__to_address(__new_begin));
+ __v.__set_valid_range(__new_begin, __v.size() + size());
+ __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+
__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
@@ -904,11 +1218,12 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (this->__begin_ != nullptr) {
+ if (__raw_begin() != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
- this->__begin_ = this->__end_ = this->__cap_ = nullptr;
+ __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __set_valid_range(nullptr, static_cast<size_type>(0));
+ __set_capacity(static_cast<size_type>(0));
}
}
@@ -925,7 +1240,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
return std::max<size_type>(2 * __cap, __new_size);
}
-// Default constructs __n objects starting at __end_
+// Default constructs __n objects starting at __end_pointer()
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -935,11 +1250,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_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->__alloc_, std::__to_address(__pos));
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos));
}
}
-// Copy constructs __n objects starting at __end_ from __x
+// Copy constructs __n objects starting at __end_pointer() from __x
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -951,7 +1266,7 @@ 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->__alloc_, std::__to_address(__pos), __x);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), __x);
}
}
@@ -960,7 +1275,8 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ =
+ std::__uninitialized_allocator_copy(__allocator_ref(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -970,22 +1286,22 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __alloc_(std::move(__x.__alloc_)) {
- this->__begin_ = __x.__begin_;
- this->__end_ = __x.__end_;
- this->__cap_ = __x.__cap_;
- __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr;
+ : __base(std::move(__x.__allocator_ref())) {
+ __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ __set_capacity(__x.__raw_capacity());
+ __x.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __x.__set_capacity(static_cast<size_type>(0));
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- if (__a == __x.__alloc_) {
- this->__begin_ = __x.__begin_;
- this->__end_ = __x.__end_;
- this->__cap_ = __x.__cap_;
- __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr;
+ : __base(__a) {
+ if (__a == __x.__allocator_ref()) {
+ __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ __set_capacity(__x.__raw_capacity());
+ __x.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __x.__set_capacity(static_cast<size_type>(0));
} else {
typedef move_iterator<iterator> _Ip;
__init_with_size(_Ip(__x.begin()), _Ip(__x.end()), __x.size());
@@ -995,7 +1311,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (__allocator_ref() != __c.__allocator_ref()) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1007,10 +1323,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- this->__begin_ = __c.__begin_;
- this->__end_ = __c.__end_;
- this->__cap_ = __c.__cap_;
- __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr;
+ __set_valid_range(__c.__raw_begin(), __c.__raw_sentinel());
+ __set_capacity(__c.__raw_capacity());
+ __c.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __c.__set_capacity(static_cast<size_type>(0));
}
template <class _Tp, class _Allocator>
@@ -1018,7 +1334,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__begin_, __x.__end_);
+ assign(__x.__raw_begin(), __x.__end_pointer());
}
return *this;
}
@@ -1027,10 +1343,11 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __begin_;
- for (; __first != __last && __cur != __end_; ++__first, (void)++__cur)
+ pointer __cur = __raw_begin();
+ pointer __end = __end_pointer();
+ for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
- if (__cur != __end_) {
+ if (__cur != __end) {
__destruct_at_end(__cur);
} else {
for (; __first != __last; ++__first)
@@ -1046,15 +1363,15 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
#if _LIBCPP_STD_VER >= 23
- auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
+ auto __mid = ranges::copy_n(std::move(__first), size(), __raw_begin()).in;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
#else
_Iterator __mid = std::next(__first, size());
- std::copy(__first, __mid, this->__begin_);
+ std::copy(__first, __mid, __raw_begin());
__construct_at_end(__mid, __last, __new_size - size());
#endif
} else {
- pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
+ pointer __m = std::__copy(std::move(__first), __last, __raw_begin()).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1068,11 +1385,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(this->__begin_, std::min(__n, __s), __u);
+ std::fill_n(__raw_begin(), std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(this->__begin_ + __n);
+ this->__destruct_at_end(__raw_begin() + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1085,7 +1402,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer<value_type, allocator_type&> __v(__n, size(), this->__alloc_);
+ __split_buffer __v(__n, size(), __allocator_ref());
__swap_out_circular_buffer(__v);
}
}
@@ -1096,7 +1413,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, allocator_type&> __v(size(), size(), this->__alloc_);
+ __split_buffer __v(size(), size(), __allocator_ref());
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1111,15 +1428,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
template <class _Tp, class _Allocator>
template <class... _Args>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), size(), __allocator_ref());
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
- return this->__end_;
+ return __raw_sentinel();
}
// This makes the compiler inline `__else()` if `__cond` is known to be false. Currently LLVM doesn't do that without
@@ -1149,18 +1466,18 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
- pointer __end = this->__end_;
+ auto __current_sentinel = __raw_sentinel();
std::__if_likely_else(
- __end < this->__cap_,
+ __current_sentinel < __raw_capacity(),
[&] {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
- ++__end;
+ ++__current_sentinel;
},
- [&] { __end = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
+ [&] { __current_sentinel = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
- this->__end_ = __end;
+ __set_sentinel(__current_sentinel);
#if _LIBCPP_STD_VER >= 17
- return *(__end - 1);
+ return back();
#endif
}
@@ -1170,8 +1487,8 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = this->__begin_ + __ps;
- this->__destruct_at_end(std::move(__p + 1, this->__end_, __p));
+ pointer __p = __raw_begin() + __ps;
+ this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1179,9 +1496,9 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = this->__begin_ + (__first - begin());
+ pointer __p = __raw_begin() + (__first - begin());
if (__first != __last) {
- this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p));
+ this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
return __make_iter(__p);
}
@@ -1189,13 +1506,13 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
- pointer __old_last = this->__end_;
+ pointer __old_last = __end_pointer();
difference_type __n = __old_last - __to;
{
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->__alloc_, std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1204,19 +1521,20 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(__x);
} else {
- __move_range(__p, this->__end_, __p + 1);
+ __move_range(__p, __end, __p + 1);
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
- if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end_), std::addressof(__x)))
+ if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end), std::addressof(__x)))
++__xr;
*__p = *__xr;
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1226,16 +1544,17 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(std::move(__x));
} else {
- __move_range(__p, this->__end_, __p + 1);
+ __move_range(__p, __end, __p + 1);
*__p = std::move(__x);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1246,17 +1565,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, std::forward<_Args>(__args)...);
- __move_range(__p, this->__end_, __p + 1);
+ __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), std::forward<_Args>(__args)...);
+ __move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1266,25 +1586,26 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = __raw_begin() + (__position - begin());
if (__n > 0) {
- if (__n <= static_cast<size_type>(this->__cap_ - this->__end_)) {
+ if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
- pointer __old_last = this->__end_;
- if (__n > static_cast<size_type>(this->__end_ - __p)) {
- size_type __cx = __n - (this->__end_ - __p);
+ pointer __end = __end_pointer();
+ pointer __old_last = __end;
+ if (__n > static_cast<size_type>(__end - __p)) {
+ size_type __cx = __n - (__end - __p);
__construct_at_end(__cx, __x);
__n -= __cx;
}
if (__n > 0) {
__move_range(__p, __old_last, __p + __old_n);
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
- if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end_), std::addressof(__x)))
+ if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end), std::addressof(__x)))
__xr += __old_n;
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1297,27 +1618,35 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = this->__begin_ + __off;
- pointer __old_last = this->__end_;
- for (; this->__end_ != this->__cap_ && __first != __last; ++__first)
+ pointer __p = __raw_begin() + __off;
+ pointer __old_last = __end_pointer();
+ for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
if (__first == __last)
- (void)std::rotate(__p, __old_last, this->__end_);
+ (void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer<value_type, allocator_type&> __v(__alloc_);
- auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, this->__end_));
+ __split_buffer __v(__allocator_ref());
+ pointer __end = __end_pointer();
+ auto __guard = std::__make_exception_guard(
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__allocator_ref(), __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
- __split_buffer<value_type, allocator_type&> __merged(
- __recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
+ __split_buffer __merged(
+ __recommend(size() + __v.size()), __off, __allocator_ref()); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__old_last), std::__to_address(this->__end_), std::__to_address(__merged.end()));
- __guard.__complete(); // Release the guard once objects in [__old_last_, __end_) have been successfully relocated.
- __merged.__set_sentinel(__merged.end() + (this->__end_ - __old_last));
- this->__end_ = __old_last;
+ __allocator_ref(),
+ std::__to_address(__old_last),
+ std::__to_address(__end_pointer()),
+ std::__to_address(__merged.end()));
+ __guard.__complete(); // Release the guard once objects in [__old_last_, __end_pointer()) have been successfully
+ // relocated.
+ __merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
+ __set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __allocator_ref(),
+ std::__to_address(__v.begin()),
+ std::__to_address(__v.end()),
+ std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1330,16 +1659,17 @@ template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = __raw_begin() + (__position - begin());
if (__n > 0) {
- if (__n <= this->__cap_ - this->__end_) {
- pointer __old_last = this->__end_;
- difference_type __dx = this->__end_ - __p;
+ if (__n <= static_cast<difference_type>(__remaining_capacity())) {
+ pointer __end = __end_pointer();
+ pointer __old_last = __end;
+ difference_type __dx = __end - __p;
if (__n > __dx) {
#if _LIBCPP_STD_VER >= 23
if constexpr (!forward_iterator<_Iterator>) {
__construct_at_end(std::move(__first), std::move(__last), __n);
- std::rotate(__p, __old_last, this->__end_);
+ std::rotate(__p, __old_last, __end);
} else
#endif
{
@@ -1355,7 +1685,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked(std::move(__first), __n, __p);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1370,12 +1700,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(__raw_begin() + __new_size);
}
}
@@ -1386,55 +1716,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(__raw_begin() + __new_size);
}
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
-#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT
-#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
-#endif
-{
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || this->__alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(this->__begin_, __x.__begin_);
- std::swap(this->__end_, __x.__end_);
- std::swap(this->__cap_, __x.__cap_);
- std::__swap_allocator(this->__alloc_, __x.__alloc_);
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
- if (this->__begin_ == nullptr) {
- if (this->__end_ != nullptr || this->__cap_ != nullptr)
- return false;
- } else {
- if (this->__begin_ > this->__end_)
- return false;
- if (this->__begin_ == this->__cap_)
- return false;
- if (this->__end_ > this->__cap_)
- return false;
- }
- return true;
-}
-
#if _LIBCPP_STD_VER >= 20
-template <>
-inline constexpr bool __format::__enable_insertable<vector<char>> = true;
+template <class _Allocator>
+inline constexpr bool __format::__enable_insertable<vector<char, _Allocator>> = true;
# if _LIBCPP_HAS_WIDE_CHARACTERS
-template <>
-inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
+template <class _Allocator>
+inline constexpr bool __format::__enable_insertable<vector<wchar_t, _Allocator>> = true;
# endif
#endif // _LIBCPP_STD_VER >= 20
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
index 85557ecbbfabc..da42ce56db30a 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
@@ -67,22 +67,6 @@ TEST_CONSTEXPR_CXX20 void test_iterators() {
}
}
-template <std::size_t N>
-constexpr void test_vector_bool() {
- { // Test swap_ranges() with aligned bytes
- std::vector<bool> f(N, false), t(N, true);
- std::ranges::swap_ranges(f, t);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
- }
- { // Test swap_ranges() with unaligned bytes
- std::vector<bool> f(N, false), t(N + 8, true);
- std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
- }
-}
-
constexpr bool test() {
{ // Validate swapping ranges directly
std::array r1 = {1, 2, 3};
@@ -183,15 +167,34 @@ constexpr bool test() {
});
});
- { // Test vector<bool>::iterator optimization
- test_vector_bool<8>();
- test_vector_bool<19>();
- test_vector_bool<32>();
- test_vector_bool<49>();
- test_vector_bool<64>();
- test_vector_bool<199>();
- test_vector_bool<256>();
+ return true;
+}
+
+// Test vector<bool>::iterator optimization
+template <std::size_t N>
+constexpr void test_vector_bool() {
+ { // Test swap_ranges() with aligned bytes
+ std::vector<bool> f(N, false), t(N, true);
+ std::ranges::swap_ranges(f, t);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
}
+ { // Test swap_ranges() with unaligned bytes
+ std::vector<bool> f(N, false), t(N + 8, true);
+ std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
+ }
+}
+
+constexpr bool test_vector_bool() {
+ test_vector_bool<8>();
+ test_vector_bool<19>();
+ test_vector_bool<32>();
+ test_vector_bool<49>();
+ test_vector_bool<64>();
+ test_vector_bool<199>();
+ test_vector_bool<256>();
return true;
}
@@ -201,5 +204,8 @@ int main(int, char**) {
test();
static_assert(test());
+ test_vector_bool();
+ static_assert(test_vector_bool());
+
return 0;
}
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 1c8ef6d7feb97..1bfdd718e36bc 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -13,6 +13,7 @@
from __future__ import print_function
import re
+import sys
import gdb
import gdb.printing
@@ -351,17 +352,28 @@ def __init__(self, val):
"""Set val, length, capacity, and iterator for bool and normal vectors."""
self.val = val
self.typename = _remove_generics(_prettify_typename(val.type))
- begin = self.val["__begin_"]
if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
+ begin = self.val["__begin_"]
self.typename += "<bool>"
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- end = self.val["__end_"]
+ for i in val.type.fields():
+ if i.is_base_class:
+ base = val[i]
+ break
+
+ begin = base["__begin_"]
+ end = base["__end_"]
self.length = end - begin
- self.capacity = self.val["__cap_"] - begin
+ for i in base.type.fields():
+ if i.name == "__cap_":
+ self.capacity = base["__cap_"] - begin
+ elif i.name == None:
+ self.capacity = base[i]["__cap_"] - begin
+ break
self.iterator = self._VectorIterator(begin, end)
def to_string(self):
>From 0580dea4fe36bd54f2b6581411f4584087411c2b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 21:14:12 +0000
Subject: [PATCH 02/39] works `__vector_layout` into `vector`
[jyknight pointed out that we'd probably end up with a smaller diff][1]
(and simpler code) if we remove the `__vector_layout` type. [This also
reduces the volume of debuginfo, as pointed out by rnk][2].
[1]: https://github.com/llvm/llvm-project/pull/155330#discussion_r2607411335
[2]: https://github.com/llvm/llvm-project/pull/155330#discussion_r2612499610
---
libcxx/include/__vector/vector.h | 712 ++++++++++++-------------------
1 file changed, 281 insertions(+), 431 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index a78ee5918517d..29cd205aeb8da 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -84,334 +84,18 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template <class _Vector, class _Tp, class _Allocator>
-class __vector_layout {
-public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = size_type;
-
- _LIBCPP_HIDE_FROM_ABI __vector_layout() = default;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
- _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __alloc_(__a) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __alloc_(std::move(__a)) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __begin_(std::move(__other.__begin_)),
- __size_(std::move(__other.__size_)),
- __cap_(std::move(__other.__cap_)),
- __alloc_(std::move(__other.__alloc_)) {
- __other.__begin_ = nullptr;
- __other.__size_ = 0;
- __other.__cap_ = 0;
- }
-
- // Capacity
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __size_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __cap_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __size_ == 0;
- }
-
- // Access
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
- return __alloc_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
- __allocator_ref() const _NOEXCEPT {
- return __alloc_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __x.__begin_);
- std::swap(__size_, __x.__size_);
- std::swap(__cap_, __x.__cap_);
- std::__swap_allocator(__alloc_, __x.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
- return __begin_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
- return __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_capacity() const _NOEXCEPT {
- return __cap_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __begin_ + __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __size_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __end - __begin_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
- __size_ = static_cast<size_type>(__pos - __begin_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
- __cap_ = static_cast<size_type>(__pos - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__size_ || __cap_)
- return false;
- } else {
- if (__size_ > __cap_)
- return false;
- }
- return true;
- }
-
-private:
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- [[no_unique_address]] allocator_type __alloc_;
-};
-#else
-template <class _Vector, class _Tp, class _Allocator>
-class __vector_layout {
-public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = pointer;
-
- // Can't be defaulted due to _LIBCPP_COMPRESSED_PAIR not being an aggregate in C++03 and C++11.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __cap_(nullptr) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
- _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __cap_(nullptr), __alloc_(__a) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __cap_(nullptr), __alloc_(std::move(__a)) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __begin_(std::move(__other.__begin_)),
- __end_(std::move(__other.__end_)),
- __cap_(std::move(__other.__cap_)),
- __alloc_(std::move(__other.__alloc_)) {
- __other.__begin_ = nullptr;
- __other.__end_ = nullptr;
- __other.__cap_ = nullptr;
- }
-
- // Capacity
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(__end_ - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __begin_ == __end_;
- }
-
- // Access
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
- return __alloc_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
- __allocator_ref() const _NOEXCEPT {
- return __alloc_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __x.__begin_);
- std::swap(__end_, __x.__end_);
- std::swap(__cap_, __x.__cap_);
- std::__swap_allocator(__alloc_, __x.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
- return __begin_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_capacity() const _NOEXCEPT {
- return __cap_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __end_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __end;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __begin_ + __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
- __end_ = __begin_ + __offset;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
- __cap_ = __begin_ + __offset;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
- return false;
- } else {
- if (__begin_ > __end_)
- return false;
- if (__begin_ == __cap_)
- return false;
- if (__end_ > __cap_)
- return false;
- }
- return true;
- }
-
-private:
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
-};
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
-
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
- using __base _LIBCPP_NODEBUG = __vector_layout<vector, _Tp, _Allocator>;
- using __self _LIBCPP_NODEBUG = vector;
- using __base::__allocator_ref;
- using __base::__end_pointer;
- using __base::__is_full;
- using __base::__raw_begin;
- using __base::__raw_capacity;
- using __base::__raw_sentinel;
- using __base::__remaining_capacity;
- using __base::__set_capacity;
- using __base::__set_sentinel;
- using __base::__set_valid_range;
- using typename __base::__alloc_traits;
- using typename __base::__sentinel_type;
- using typename __base::__split_buffer;
-
+class vector {
public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using reference = typename __base::reference;
- using const_reference = typename __base::const_reference;
- using size_type = typename __base::size_type;
- using difference_type = typename __base::difference_type;
- using pointer = typename __base::pointer;
- using const_pointer = typename __base::const_pointer;
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
// Users might provide custom allocators, and prior to C++20 we have no existing way to detect whether the allocator's
// pointer type is contiguous (though it has to be by the Standard). Using the wrapper type ensures the iterator is
@@ -425,8 +109,6 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using __base::__invariants;
-
// A vector contains the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
// - allocator_type: may be trivially relocatable, so it's checked
@@ -451,7 +133,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#else
noexcept
#endif
- : __base(__a) {
+ : __alloc_(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -465,7 +147,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -487,7 +169,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -510,7 +192,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
__init_with_sentinel(__first, __last);
}
@@ -531,7 +213,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -540,7 +222,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __base(__alloc) {
+ : __alloc_(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -557,10 +239,10 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__raw_begin() != nullptr) {
+ if (__vec_.__begin_ != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__allocator_ref(), __vec_.__raw_begin(), __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity());
}
}
@@ -572,13 +254,13 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __base(__alloc_traits::select_on_container_copy_construction(__x.__allocator_ref())) {
- __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
+ : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) {
+ __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __base(__a) {
- __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
+ : __alloc_(__a) {
+ __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -589,7 +271,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -652,17 +334,17 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return __allocator_ref();
+ return __alloc_;
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__raw_begin()));
+ return __make_iter(__add_alignment_assumption(__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__raw_begin()));
+ return __make_iter(__add_alignment_assumption(__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
return __make_iter(__add_alignment_assumption(__end_pointer()));
@@ -704,17 +386,30 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
//
// Capacity
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __base::size();
+ return __size_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __base::capacity();
+ return __cap_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __base::empty();
+ return __size_ == 0;
}
+#else
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __begin_);
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __begin_ == __end_;
+ }
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(__allocator_ref()), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__alloc_), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -724,48 +419,62 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__raw_begin();
+ return *__begin_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__raw_begin();
+ return *__begin_;
}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- return __base::back();
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+#else
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- return __base::back();
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
}
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(__raw_begin());
+ return std::__to_address(__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(__raw_begin());
+ return std::__to_address(__begin_);
}
//
@@ -790,7 +499,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -802,12 +511,12 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
if (__len < __raw_capacity() - __raw_sentinel()) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- __split_buffer __buffer(__recommend(size() + __len), size(), __allocator_ref());
+ __split_buffer __buffer(__recommend(size() + __len), size(), __alloc_);
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
} else {
- vector __buffer(__allocator_ref());
+ vector __buffer(__alloc_);
for (auto&& __val : __range)
__buffer.emplace_back(std::forward<decltype(__val)>(__val));
append_range(ranges::as_rvalue_view(__buffer));
@@ -873,7 +582,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(__raw_begin());
+ __base_destruct_at_end(__begin_);
__annotate_shrink(__old_size);
}
@@ -887,10 +596,151 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
#endif
{
- __base::swap(__other);
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __other.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __other.__begin_);
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ std::swap(__size_, __other.__size_);
+#else
+ std::swap(__end_, __other.__end_);
+#endif
+ std::swap(__cap_, __other.__cap_);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+public:
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ != 0 || __cap_ != 0)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+private:
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ return __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __size_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __end - __begin_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ __size_ = __size;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __size_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ __cap_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
+#else
+public:
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+ }
private:
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __end_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __begin_ + __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __end_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
@@ -903,7 +753,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(__allocator_ref(), __n);
+ auto __allocation = std::__allocate_at_least(__alloc_, __n);
__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__set_capacity(__allocation.count);
__annotate_new(0);
@@ -954,7 +804,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), *__first);
+ __temp_value<value_type, _Allocator> __tmp(__alloc_, *__first);
*__position = std::move(__tmp.get());
}
}
@@ -992,7 +842,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(__raw_begin()),
+ std::__wrap_iter<pointer>(__begin_),
std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
@@ -1004,7 +854,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(__raw_begin()),
+ std::__wrap_iter<const_pointer>(__begin_),
std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
@@ -1068,7 +918,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
__v_.__set_sentinel(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__raw_begin());
+ __v_.__annotate_shrink(__new_end_ - __v_.__begin_);
}
}
@@ -1083,7 +933,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(__allocator_ref(), std::__to_address(--__soon_to_be_end));
+ __alloc_traits::destroy(__alloc_, std::__to_address(--__soon_to_be_end));
__set_sentinel(__new_last);
}
@@ -1102,21 +952,21 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (__allocator_ref() != __c.__allocator_ref()) {
+ if (__alloc_ != __c.__alloc_) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __alloc_traits::deallocate(__alloc_, __begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<__sentinel_type>(0));
}
- __allocator_ref() = __c.__allocator_ref();
+ __alloc_ = __c.__alloc_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __allocator_ref() = std::move(__c.__allocator_ref());
+ __alloc_ = std::move(__c.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -1137,7 +987,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer& __sb) {
- auto __vector_begin = __raw_begin();
+ auto __vector_begin = __begin_;
auto __vector_sentinel = __raw_sentinel();
auto __vector_cap = __raw_capacity();
@@ -1174,7 +1024,7 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__raw_begin(), size()) into the front of __v and swaps the
+// __swap_out_circular_buffer relocates the objects in [__begin_, size()) into the front of __v and swaps the
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
@@ -1182,8 +1032,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
- std::__to_address(__raw_begin()),
+ __alloc_,
+ std::__to_address(__begin_),
std::__to_address(__end_pointer()),
std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
@@ -1195,10 +1045,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__raw_begin(), __p) into the front of __v, the objects in
+// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __raw_begin()) objects in the front and space for at least (size() - __p) objects in the back. This
-// function has a strong exception guarantee if __raw_begin() == __p || size() == __p.
+// exactly (__p - __begin_) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __begin_ == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) {
@@ -1206,18 +1056,18 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
pointer __ret = __v.begin();
pointer __end = __end_pointer();
- // Relocate [__p, __end) first to avoid having a hole in [__raw_begin(), __end)
- // in case something in [__raw_begin(), __p) throws.
+ // Relocate [__p, __end) first to avoid having a hole in [__begin_, __end)
+ // in case something in [__begin_, __p) throws.
std::__uninitialized_allocator_relocate(
- __allocator_ref(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ __alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
__set_sentinel(
__raw_sentinel() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __raw_begin());
+ auto __new_begin = __v.begin() - (__p - __begin_);
std::__uninitialized_allocator_relocate(
- __allocator_ref(), std::__to_address(__raw_begin()), std::__to_address(__p), std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
@@ -1229,10 +1079,10 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (__raw_begin() != nullptr) {
+ if (__begin_ != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __alloc_traits::deallocate(__alloc_, __begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<size_type>(0));
}
@@ -1261,7 +1111,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_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(__allocator_ref(), std::__to_address(__pos));
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos));
}
}
@@ -1277,7 +1127,7 @@ 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(__allocator_ref(), std::__to_address(__pos), __x);
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos), __x);
}
}
@@ -1287,7 +1137,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
__tx.__pos_ =
- std::__uninitialized_allocator_copy(__allocator_ref(), std::move(__first), std::move(__last), __tx.__pos_);
+ std::__uninitialized_allocator_copy(__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1297,8 +1147,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __base(std::move(__x.__allocator_ref())) {
- __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ : __alloc_(std::move(__x.__alloc_)) {
+ __set_valid_range(__x.__begin_, __x.__raw_sentinel());
__set_capacity(__x.__raw_capacity());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
@@ -1307,9 +1157,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __base(__a) {
- if (__a == __x.__allocator_ref()) {
- __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ : __alloc_(__a) {
+ if (__a == __x.__alloc_) {
+ __set_valid_range(__x.__begin_, __x.__raw_sentinel());
__set_capacity(__x.__raw_capacity());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
@@ -1322,7 +1172,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (__allocator_ref() != __c.__allocator_ref()) {
+ if (__alloc_ != __c.__alloc_) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1334,7 +1184,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- __set_valid_range(__c.__raw_begin(), __c.__raw_sentinel());
+ __set_valid_range(__c.__begin_, __c.__raw_sentinel());
__set_capacity(__c.__raw_capacity());
__c.__set_valid_range(nullptr, static_cast<size_type>(0));
__c.__set_capacity(static_cast<size_type>(0));
@@ -1345,7 +1195,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__raw_begin(), __x.__end_pointer());
+ assign(__x.__begin_, __x.__end_pointer());
}
return *this;
}
@@ -1354,7 +1204,7 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __raw_begin();
+ pointer __cur = __begin_;
pointer __end = __end_pointer();
for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
@@ -1374,10 +1224,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
auto const __size = size();
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __raw_begin()).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, __raw_begin()).second;
+ pointer __m = std::__copy(std::move(__first), __last, __begin_).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1391,11 +1241,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(__raw_begin(), std::min(__n, __s), __u);
+ std::fill_n(__begin_, std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(__raw_begin() + __n);
+ this->__destruct_at_end(__begin_ + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1408,7 +1258,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer __v(__n, size(), __allocator_ref());
+ __split_buffer __v(__n, size(), __alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1419,7 +1269,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer __v(size(), size(), __allocator_ref());
+ __split_buffer __v(size(), size(), __alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1436,10 +1286,10 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer __v(__recommend(size() + 1), size(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), size(), __alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
return __raw_sentinel();
@@ -1493,7 +1343,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = __raw_begin() + __ps;
+ pointer __p = __begin_ + __ps;
this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1502,7 +1352,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = __raw_begin() + (__first - begin());
+ pointer __p = __begin_ + (__first - begin());
if (__first != __last) {
this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
@@ -1518,7 +1368,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(__allocator_ref(), std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1527,7 +1377,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1540,7 +1390,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1550,7 +1400,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1560,7 +1410,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1571,18 +1421,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(__alloc_, std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1592,7 +1442,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (__n > 0) {
if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
@@ -1611,7 +1461,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1624,7 +1474,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = __raw_begin() + __off;
+ pointer __p = __begin_ + __off;
pointer __old_last = __end_pointer();
for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
@@ -1632,15 +1482,15 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
if (__first == __last)
(void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer __v(__allocator_ref());
+ __split_buffer __v(__alloc_);
pointer __end = __end_pointer();
auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__allocator_ref(), __old_last, __end));
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
__split_buffer __merged(
- __recommend(size() + __v.size()), __off, __allocator_ref()); // has `__off` positions available at the front
+ __recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
+ __alloc_,
std::__to_address(__old_last),
std::__to_address(__end_pointer()),
std::__to_address(__merged.end()));
@@ -1649,7 +1499,7 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
__set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
+ __alloc_,
std::__to_address(__v.begin()),
std::__to_address(__v.end()),
std::__to_address(__merged.end()));
@@ -1665,7 +1515,7 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (__n > 0) {
if (__n <= static_cast<difference_type>(__remaining_capacity())) {
pointer __end = __end_pointer();
@@ -1691,7 +1541,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1706,12 +1556,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__raw_begin() + __new_size);
+ this->__destruct_at_end(__begin_ + __new_size);
}
}
@@ -1722,12 +1572,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__raw_begin() + __new_size);
+ this->__destruct_at_end(__begin_ + __new_size);
}
}
>From f502629b7f53444056ef164cb057e2d321e1ea05 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 22:48:54 +0000
Subject: [PATCH 03/39] further reduces the diff
0580dea significantly reduced the diff by returning the stable ABI code
to its original location. `__vector_base` did away with using `this->`
for most things, since it's largely redundant, but these were left out
in 0580dea. This commit adds most of those back.
---
libcxx/include/__vector/vector.h | 194 ++++++++++++++++---------------
1 file changed, 100 insertions(+), 94 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 29cd205aeb8da..28465a6b4c44d 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -334,17 +334,17 @@ class vector {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return __alloc_;
+ return this->__alloc_;
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
return __make_iter(__add_alignment_assumption(__end_pointer()));
@@ -398,18 +398,18 @@ class vector {
}
#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(__end_ - __begin_);
+ return static_cast<size_type>(this->__end_ - this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __begin_);
+ return static_cast<size_type>(this->__cap_ - this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __begin_ == __end_;
+ return this->__begin_ == this->__end_;
}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(__alloc_), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -419,31 +419,31 @@ class vector {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__begin_;
+ return *this->__begin_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__begin_;
+ return *this->__begin_;
}
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -458,11 +458,11 @@ class vector {
#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
+ return *(this->__end_ - 1);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
+ return *(this->__end_ - 1);
}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -470,11 +470,11 @@ class vector {
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(__begin_);
+ return std::__to_address(this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(__begin_);
+ return std::__to_address(this->__begin_);
}
//
@@ -499,7 +499,7 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -582,7 +582,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(__begin_);
+ __base_destruct_at_end(this->__begin_);
__annotate_shrink(__old_size);
}
@@ -610,18 +610,10 @@ class vector {
std::__swap_allocator(__alloc_, __other.__alloc_);
}
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-public:
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__size_ != 0 || __cap_ != 0)
- return false;
- } else {
- if (__size_ > __cap_)
- return false;
- }
- return true;
- }
private:
using __sentinel_type _LIBCPP_NODEBUG = size_type;
using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
@@ -671,21 +663,6 @@ class vector {
size_type __cap_ = 0;
[[no_unique_address]] allocator_type __alloc_;
#else
-public:
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
- return false;
- } else {
- if (__begin_ > __end_)
- return false;
- if (__begin_ == __cap_)
- return false;
- if (__end_ > __cap_)
- return false;
- }
- return true;
- }
private:
using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
using __sentinel_type _LIBCPP_NODEBUG = pointer;
@@ -753,7 +730,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(__alloc_, __n);
+ auto __allocation = std::__allocate_at_least(this->__alloc_, __n);
__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__set_capacity(__allocation.count);
__annotate_new(0);
@@ -804,7 +781,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(__alloc_, *__first);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc_, *__first);
*__position = std::move(__tmp.get());
}
}
@@ -842,7 +819,7 @@ class vector {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(__begin_),
+ std::__wrap_iter<pointer>(this->__begin_),
std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
@@ -854,7 +831,7 @@ class vector {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(__begin_),
+ std::__wrap_iter<const_pointer>(this->__begin_),
std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
@@ -933,7 +910,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(__alloc_, std::__to_address(--__soon_to_be_end));
+ __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end));
__set_sentinel(__new_last);
}
@@ -952,21 +929,21 @@ class vector {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (__alloc_ != __c.__alloc_) {
+ if (this->__alloc_ != __c.__alloc_) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__alloc_, __begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<__sentinel_type>(0));
}
- __alloc_ = __c.__alloc_;
+ this->__alloc_ = __c.__alloc_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __alloc_ = std::move(__c.__alloc_);
+ this->__alloc_ = std::move(__c.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -1032,7 +1009,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- __alloc_,
+ this->__alloc_,
std::__to_address(__begin_),
std::__to_address(__end_pointer()),
std::__to_address(__new_begin));
@@ -1059,7 +1036,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
// Relocate [__p, __end) first to avoid having a hole in [__begin_, __end)
// in case something in [__begin_, __p) throws.
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ this->__alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
__set_sentinel(
@@ -1067,7 +1044,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
auto __new_begin = __v.begin() - (__p - __begin_);
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
+ this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
@@ -1079,10 +1056,10 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (__begin_ != nullptr) {
+ if (this->__begin_ != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__alloc_, __begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<size_type>(0));
}
@@ -1111,7 +1088,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_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(__alloc_, std::__to_address(__pos));
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos));
}
}
@@ -1127,7 +1104,7 @@ 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(__alloc_, std::__to_address(__pos), __x);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), __x);
}
}
@@ -1136,8 +1113,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ =
- std::__uninitialized_allocator_copy(__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1172,7 +1148,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (__alloc_ != __c.__alloc_) {
+ if (this->__alloc_ != __c.__alloc_) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1224,10 +1200,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
auto const __size = size();
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __begin_).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, __begin_).second;
+ pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1241,11 +1217,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(__begin_, std::min(__n, __s), __u);
+ std::fill_n(this->__begin_, std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(__begin_ + __n);
+ this->__destruct_at_end(this->__begin_ + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1258,7 +1234,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer __v(__n, size(), __alloc_);
+ __split_buffer __v(__n, size(), this->__alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1269,7 +1245,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer __v(size(), size(), __alloc_);
+ __split_buffer __v(size(), size(), this->__alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1286,10 +1262,10 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer __v(__recommend(size() + 1), size(), __alloc_);
+ __split_buffer __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
return __raw_sentinel();
@@ -1343,7 +1319,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = __begin_ + __ps;
+ pointer __p = this->__begin_ + __ps;
this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1352,7 +1328,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = __begin_ + (__first - begin());
+ pointer __p = this->__begin_ + (__first - begin());
if (__first != __last) {
this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
@@ -1368,7 +1344,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(__alloc_, std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1377,7 +1353,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1390,7 +1366,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1400,7 +1376,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1410,7 +1386,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1421,18 +1397,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(__alloc_, std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc_, std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1442,7 +1418,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (__n > 0) {
if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
@@ -1461,7 +1437,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1474,7 +1450,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = __begin_ + __off;
+ pointer __p = this->__begin_ + __off;
pointer __old_last = __end_pointer();
for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
@@ -1515,7 +1491,7 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (__n > 0) {
if (__n <= static_cast<difference_type>(__remaining_capacity())) {
pointer __end = __end_pointer();
@@ -1541,7 +1517,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1556,12 +1532,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, this->__alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ + __new_size);
}
}
@@ -1577,16 +1553,46 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ + __new_size);
+ }
+}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template<class _Tp, class _Allocator>
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ != 0 || __cap_ != 0)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
}
+ return true;
}
+#else
+template<class _Tp, class _Allocator>
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+}
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
#if _LIBCPP_STD_VER >= 20
-template <class _Allocator>
-inline constexpr bool __format::__enable_insertable<vector<char, _Allocator>> = true;
+template <>
+inline constexpr bool __format::__enable_insertable<vector<char>> = true;
# if _LIBCPP_HAS_WIDE_CHARACTERS
-template <class _Allocator>
-inline constexpr bool __format::__enable_insertable<vector<wchar_t, _Allocator>> = true;
+template <>
+inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
# endif
#endif // _LIBCPP_STD_VER >= 20
>From 935405c3d732684229ed15ba4721d0fcb4fde9cb Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 23:25:20 +0000
Subject: [PATCH 04/39] fixes breaks from generic-cxx20
---
libcxx/include/__vector/vector.h | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 28465a6b4c44d..ea56b3ecc65b3 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -676,7 +676,7 @@ class vector {
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __end_;
+ return __cap_ - __end_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
@@ -695,16 +695,12 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
__end_ = __begin_ + __offset;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
- __cap_ = __begin_ + __offset;
- }
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
__cap_ = __begin_ + __offset;
}
>From 970d4588c0e261f762b47258b6bc620b8825fdaf Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 14 Jan 2026 01:38:47 +0000
Subject: [PATCH 05/39] further reduces diff
---
libcxx/include/__split_buffer | 3 +-
libcxx/include/__vector/vector.h | 187 ++++++++++++++++---------------
2 files changed, 99 insertions(+), 91 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1b1492dadaddc..da26a6e74935a 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -310,7 +310,8 @@ public:
return __begin_[__size_ - 1];
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(__split_buffer_size_layout& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_without_allocator(__split_buffer_size_layout& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index ea56b3ecc65b3..2ffa67453adc9 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -87,6 +87,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
public:
+ ///
+ /// Types
+ ///
using value_type = _Tp;
using allocator_type = _Allocator;
using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
@@ -589,97 +592,87 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector& __other)
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT
+ _NOEXCEPT;
#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
#endif
- {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __other.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __other.__begin_);
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- std::swap(__size_, __other.__size_);
-#else
- std::swap(__end_, __other.__end_);
-#endif
- std::swap(__cap_, __other.__cap_);
- std::__swap_allocator(__alloc_, __other.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+
private:
- using __sentinel_type _LIBCPP_NODEBUG = size_type;
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
return __size_;
- }
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __begin_ + __size_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __size_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
return __size_ == __cap_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
__begin_ = __begin;
- __size_ = __end - __begin_;
- }
+ __size_ = __end - __begin_;
+ }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
__begin_ = __begin;
__size_ = __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
__size_ = __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
__size_ = static_cast<size_type>(__pos - __begin_);
- }
+ }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
__cap_ = static_cast<size_type>(__pos - __begin_);
- }
+ }
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- [[no_unique_address]] allocator_type __alloc_;
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
#else
+
private:
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = pointer;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
return __end_;
}
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __end_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __end_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __end_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
return __end_ == __cap_;
}
@@ -688,29 +681,31 @@ class vector {
__end_ = __end;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
__begin_ = __begin;
__end_ = __begin_ + __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
__end_ = __begin_ + __offset;
- }
+ }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
__cap_ = __begin_ + __offset;
}
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20
+ _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
return __cap_;
}
@@ -834,8 +829,7 @@ class vector {
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
__swap_out_circular_buffer(__split_buffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
@@ -851,7 +845,8 @@ class vector {
}
template <class... _Args>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __emplace_back_slow_path(_Args&&... __args);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline __sentinel_type
+ __emplace_back_slow_path(_Args&&... __args);
// The following functions are no-ops outside of AddressSanitizer mode.
// We call annotations for every allocator, unless explicitly disabled.
@@ -1005,13 +1000,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc_,
- std::__to_address(__begin_),
- std::__to_address(__end_pointer()),
- std::__to_address(__new_begin));
+ this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_pointer()), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
- // __v.__size_ += __size_;
__swap_layouts(__v);
__v.__set_data(__v.begin());
@@ -1194,8 +1185,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n) {
size_type __new_size = static_cast<size_type>(__n);
if (__new_size <= capacity()) {
- if (__new_size > size()) {
- auto const __size = size();
+ auto const __size = size();
+ if (__new_size > __size) {
auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
@@ -1462,19 +1453,13 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__split_buffer __merged(
__recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__old_last),
- std::__to_address(__end_pointer()),
- std::__to_address(__merged.end()));
+ __alloc_, std::__to_address(__old_last), std::__to_address(__end_pointer()), std::__to_address(__merged.end()));
__guard.__complete(); // Release the guard once objects in [__old_last_, __end_pointer()) have been successfully
// relocated.
__merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
__set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__v.begin()),
- std::__to_address(__v.end()),
- std::__to_address(__merged.end()));
+ __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1528,7 +1513,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, this->__alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
@@ -1553,9 +1538,31 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
}
}
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
+#if _LIBCPP_STD_VER >= 14
+ _NOEXCEPT
+#else
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
+#endif
+{
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(this->__begin_, __x.__begin_);
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template<class _Tp, class _Allocator>
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ std::swap(this->__size_, __x.__size_);
+#else
+ std::swap(this->__end_, __x.__end_);
+#endif
+ std::swap(this->__cap_, __x.__cap_);
+ std::__swap_allocator(this->__alloc_, __x.__alloc_);
+}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
if (__begin_ == nullptr) {
if (__size_ != 0 || __cap_ != 0)
return false;
@@ -1566,17 +1573,17 @@ template<class _Tp, class _Allocator>
return true;
}
#else
-template<class _Tp, class _Allocator>
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
+ if (this->__begin_ == nullptr) {
+ if (this->__end_ != nullptr || this->__cap_ != nullptr)
return false;
} else {
- if (__begin_ > __end_)
+ if (this->__begin_ > this->__end_)
return false;
- if (__begin_ == __cap_)
+ if (this->__begin_ == this->__cap_)
return false;
- if (__end_ > __cap_)
+ if (this->__end_ > this->__cap_)
return false;
}
return true;
>From c87e88382d31e74a946bbc3f58c213dae1324d15 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 14 Jan 2026 02:35:00 +0000
Subject: [PATCH 06/39] gets GDB pretty-printer working
---
libcxx/utils/gdb/libcxx/printers.py | 32 ++++++++++++++---------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 1bfdd718e36bc..83df6be78a1bb 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -13,7 +13,6 @@
from __future__ import print_function
import re
-import sys
import gdb
import gdb.printing
@@ -352,28 +351,29 @@ def __init__(self, val):
"""Set val, length, capacity, and iterator for bool and normal vectors."""
self.val = val
self.typename = _remove_generics(_prettify_typename(val.type))
+ begin = self.val["__begin_"]
if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
- begin = self.val["__begin_"]
self.typename += "<bool>"
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- for i in val.type.fields():
- if i.is_base_class:
- base = val[i]
- break
-
- begin = base["__begin_"]
- end = base["__end_"]
- self.length = end - begin
- for i in base.type.fields():
- if i.name == "__cap_":
- self.capacity = base["__cap_"] - begin
- elif i.name == None:
- self.capacity = base[i]["__cap_"] - begin
- break
+ cap = self.val["__cap_"]
+
+ # We test for integers because `vector<T>::size_type` is required to
+ # be an unsigned integer, whereas `vector<T>::pointer` can be any
+ # type that satisfies the Cpp17NullablePointer requirements.
+ if cap.type.strip_typedefs().code == gdb.TYPE_CODE_INT:
+ size = self.val["__size_"]
+ self.length = size
+ self.capacity = cap
+ end = begin + size
+ else:
+ end = self.val["__end_"]
+ self.length = end - begin
+ self.capacity = cap - begin
+
self.iterator = self._VectorIterator(begin, end)
def to_string(self):
>From 44adc2d0c03ea421871d7a9b2aaa178ad828b1b7 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 15 Jan 2026 01:10:06 +0000
Subject: [PATCH 07/39] ensures that generic-cxx23 passes
---
libcxx/include/__vector/vector.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 2ffa67453adc9..46635045bc704 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -510,8 +510,8 @@ class vector {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
- auto __len = static_cast<size_type>(ranges::distance(__range));
- if (__len < __raw_capacity() - __raw_sentinel()) {
+ auto __len = ranges::distance(__range);
+ if (__len < static_cast<difference_type>(__raw_capacity() - __raw_sentinel())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
__split_buffer __buffer(__recommend(size() + __len), size(), __alloc_);
>From fe98721a13c700986159e12a90a20134daf671b9 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 15 Jan 2026 02:23:38 +0000
Subject: [PATCH 08/39] attempts to fix GCC issue
---
libcxx/include/__vector/vector.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 46635045bc704..18004abbd1899 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -86,6 +86,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+#else
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+#endif
public:
///
/// Types
@@ -605,7 +610,6 @@ class vector {
private:
using __sentinel_type _LIBCPP_NODEBUG = size_type;
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
return __size_;
@@ -656,7 +660,6 @@ class vector {
#else
private:
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
using __sentinel_type _LIBCPP_NODEBUG = pointer;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
>From 81b360bf70d0dddb5e416159e43262f8f9c1655f Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 16 Jan 2026 01:42:32 +0000
Subject: [PATCH 09/39] replaces alias to comply with GCC's -Wchanges-meaning
---
libcxx/include/__vector/vector.h | 52 ++++++++++++++++++++------------
1 file changed, 32 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 18004abbd1899..309fa0502752a 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -87,10 +87,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+ template <class _SplitBuffer, class _Tp2, class _Allocator2>
+ using __split_buffer_layout _LIBCPP_NODEBUG = __split_buffer_size_layout<_SplitBuffer, _Tp2, _Allocator2>;
#else
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ template <class _SplitBuffer, class _Tp2, class _Allocator2>
+ using __split_buffer_layout _LIBCPP_NODEBUG = __split_buffer_pointer_layout<_SplitBuffer, _Tp2, _Allocator2>;
#endif
+
public:
///
/// Types
@@ -519,7 +522,7 @@ class vector {
if (__len < static_cast<difference_type>(__raw_capacity() - __raw_sentinel())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- __split_buffer __buffer(__recommend(size() + __len), size(), __alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __buffer(__recommend(size() + __len), size(), __alloc_);
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
@@ -832,9 +835,10 @@ class vector {
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(__split_buffer& __v, pointer __p);
+ __swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -957,7 +961,8 @@ class vector {
return __p;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer& __sb) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_layouts(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __sb) {
auto __vector_begin = __begin_;
auto __vector_sentinel = __raw_sentinel();
auto __vector_cap = __raw_capacity();
@@ -999,7 +1004,8 @@ vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
@@ -1018,7 +1024,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
// function has a strong exception guarantee if __begin_ == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v,
+ pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
@@ -1224,7 +1231,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer __v(__n, size(), this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__n, size(), this->__alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1235,7 +1242,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer __v(size(), size(), this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(size(), size(), this->__alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1252,7 +1259,7 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer __v(__recommend(size() + 1), size(), this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
@@ -1356,7 +1363,8 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1376,7 +1384,8 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1398,7 +1407,8 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1427,7 +1437,8 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ __recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1448,12 +1459,12 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
if (__first == __last)
(void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer __v(__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__alloc_);
pointer __end = __end_pointer();
auto __guard = std::__make_exception_guard(
_AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
- __split_buffer __merged(
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __merged(
__recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
__alloc_, std::__to_address(__old_last), std::__to_address(__end_pointer()), std::__to_address(__merged.end()));
@@ -1501,7 +1512,8 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ __recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1516,7 +1528,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
@@ -1532,7 +1544,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
>From ff25eb8f2210893f4699e564634e576cb068575f Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 20 Jan 2026 21:36:48 +0000
Subject: [PATCH 10/39] Revert "replaces alias to comply with GCC's
-Wchanges-meaning"
This reverts commit 81b360bf70d0dddb5e416159e43262f8f9c1655f.
---
libcxx/include/__vector/vector.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 309fa0502752a..0a6a572c87a37 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -93,7 +93,6 @@ class vector {
template <class _SplitBuffer, class _Tp2, class _Allocator2>
using __split_buffer_layout _LIBCPP_NODEBUG = __split_buffer_pointer_layout<_SplitBuffer, _Tp2, _Allocator2>;
#endif
-
public:
///
/// Types
>From bafc15386fdef256752b34cde86b6572911cc315 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 20 Jan 2026 21:35:29 +0000
Subject: [PATCH 11/39] renames __split_buffer to comply with GCC's
-Wchanges-meaning
---
libcxx/include/__vector/vector.h | 42 +++++++++++++++-----------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 0a6a572c87a37..f6a5a6453a2d0 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -87,11 +87,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- template <class _SplitBuffer, class _Tp2, class _Allocator2>
- using __split_buffer_layout _LIBCPP_NODEBUG = __split_buffer_size_layout<_SplitBuffer, _Tp2, _Allocator2>;
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
#else
- template <class _SplitBuffer, class _Tp2, class _Allocator2>
- using __split_buffer_layout _LIBCPP_NODEBUG = __split_buffer_pointer_layout<_SplitBuffer, _Tp2, _Allocator2>;
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
#endif
public:
///
@@ -521,7 +519,7 @@ class vector {
if (__len < static_cast<difference_type>(__raw_capacity() - __raw_sentinel())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __buffer(__recommend(size() + __len), size(), __alloc_);
+ _SplitBuffer __buffer(__recommend(size() + __len), size(), __alloc_);
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
@@ -835,9 +833,9 @@ class vector {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v);
+ __swap_out_circular_buffer(_SplitBuffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v, pointer __p);
+ __swap_out_circular_buffer(_SplitBuffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -961,7 +959,7 @@ class vector {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_layouts(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __sb) {
+ __swap_layouts(_SplitBuffer& __sb) {
auto __vector_begin = __begin_;
auto __vector_sentinel = __raw_sentinel();
auto __vector_cap = __raw_capacity();
@@ -1004,7 +1002,7 @@ vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
@@ -1023,7 +1021,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<_Tp, _Allocat
// function has a strong exception guarantee if __begin_ == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<_Tp, _Allocator, __split_buffer_layout>& __v,
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
@@ -1230,7 +1228,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__n, size(), this->__alloc_);
+ _SplitBuffer __v(__n, size(), this->__alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1241,7 +1239,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(size(), size(), this->__alloc_);
+ _SplitBuffer __v(size(), size(), this->__alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1258,7 +1256,7 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(size() + 1), size(), this->__alloc_);
+ _SplitBuffer __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
@@ -1362,7 +1360,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ _SplitBuffer __v(
__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
@@ -1383,7 +1381,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ _SplitBuffer __v(
__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
@@ -1406,7 +1404,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ _SplitBuffer __v(
__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
@@ -1436,7 +1434,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ _SplitBuffer __v(
__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
@@ -1458,12 +1456,12 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
if (__first == __last)
(void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__alloc_);
+ _SplitBuffer __v(__alloc_);
pointer __end = __end_pointer();
auto __guard = std::__make_exception_guard(
_AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __merged(
+ _SplitBuffer __merged(
__recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
__alloc_, std::__to_address(__old_last), std::__to_address(__end_pointer()), std::__to_address(__merged.end()));
@@ -1511,7 +1509,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(
+ _SplitBuffer __v(
__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
@@ -1527,7 +1525,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(__new_size), __current_size, __alloc_);
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
@@ -1543,7 +1541,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer<_Tp, _Allocator, __split_buffer_layout> __v(__recommend(__new_size), __current_size, __alloc_);
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
>From 7627e34033eb7e8fb95b2bfe813a2b30e8bbf7f4 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 27 Jan 2026 18:12:20 +0000
Subject: [PATCH 12/39] [libcxx] fixes `__split_buffer_size_layout` bugs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
**tl;dr**
As `__split_buffer` doesn't have any unit tests, and because #139632
disassociated adding `__split_buffer` support for both pointer-based
and size-based layouts from its `vector` counterpart, libc++ had no
way to expose `__split_buffer_size_layout` bugs until the size-based
vector patch integrated #139632. This commit fixes the two problems
that were identified while working on #155330.
**Context**
* `__split_buffer_size_layout` needs to update its size whenever
`__begin_` is adjusted (relative to `__front_`).
* `__split_buffer`'s layout types originally updated `__begin_`
independently of the sentinel type, via `__set_begin()` and
`__set_sentinel()`, respectively.
* [Louis Dionne observed that `__set_begin()` was always coupled
with `__set_sentinel()`][1], and suggested combining them into
a single setter. This feedback was applied in ec20ccc.
**What went wrong (part 1)**
ec20ccc combined `__set_begin()` and `__set_sentinel()` into a single
function, but didn't remove the overlapping behaviour for
`__split_buffer_size_layout`. The code below shows how this caused a
problem:
```
void __set_valid_range(pointer __new_begin, pointer __new_end)
{
__size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
__set_sentinel(__new_end);
// Inlining call to `__set_sentinel(__new_end)`:
// __size_ += __new_end - end();
//
// Inlining call to `end()`:
// __size_ += __new_end - (__begin_ + __size_);
}
```
`__set_valid_range(pointer, pointer)` sets `__size_` on both sides of
setting `__begin_`. While either is valid on its own, applying both is
incorrect. `__set_valid_range(pointer, size_type)` has the same abstract
logic, but only wastes compute cycles, rather than affecting
correctness:
```
void __set_valid_range(pointer __new_begin, size_type __new_size)
{
__size_ -= __new_begin_ - __begin_;
__begin_ = __new_begin_;
__set_sentinel(__new_size);
// Inlining call to `__set_sentinel(__new_size)`:
// __size = __new_size;
//
// First line is an efficiency bug, not a correctness bug.
}
```
This commit removes the first line both overloads. Additionally, this
commit optimises `__set_sentinel(pointer)` computes, as described
below:
```
__set_sentinel(__new_end)
≡ __size_ += __new_end - end()
≡ __size_ += __new_end - (__begin_ + __size_)
≡ __size_ = __size_ + __new_end - (__begin_ + __size_)
= __size_ + __new_end - __begin_ - __size_
= __new_end - __begin_
```
**What went wrong (part 2)**
The second bug was a type error in `__swap_without_allocator`. As most
function signatures identical in both layout types, they were copied
from `__split_buffer_pointer_layout` into `__split_buffer_size_layout`
to ensure that they were correct. `__swap_without_allocator` is a member
function that operates on the layout type directly, and so its signature
needs to differ with each layout type. Although other member functions
were adjusted (e.g. `swap`), `__swap_without_allocator` was not, leading
to compile-time errors when working on size-based vector, since
`__split_buffer_pointer_layout` is not used when `vector` is size-based.
**How this ended up in the main branch**
Since the size-based vector project applies very similar changes to
`__split_buffer` and `std::vector`, it was split into two PRs, so that
reviewers didn't need to provide duplicate feedback. The PRs were split
on types: #139632 patches `__split_buffer` and #155330 patches `vector`.
Since `vector` needs a layout-compatible `__split_buffer`, #139632 was
merged before #155330, to keep the PR story as simple as possible.
`__split_buffer` is an implementation detail and does not have its own
unit tests: correctness bugs are being surfaced by its drivers, namely
`std::vector` and `std::deque`. As such, there isn't a way to identify
that `__split_buffer_size_layout` was correct without paradoxically
testing it alongside a size-based vector implementation.
**How this can be avoided in the future**
There are two primary ways to avoid this type of problem moving forward.
1. **Split work across logic instead of types.** #139632 could have
introduced the pointer layouts for both `__split_buffer` and
`vector`, which would have set the structure for both types, but not
made any material changes to the implementation. This would have
coupled dependencies instead of typenames, and possibly simplified
the review process further, as no logic would have changed.
The trade-off for this approach is that both layouts influenced the
layout's API design, and might have initially favoured the pointer
layout, leading to adjustments later on.
2. **Stack dependent PRs, and submit when all have been LGTM'd.** This
approach would allow the PRs to be sent for review as they were, but
ensures that logic that's coupled across commits is checked in
together. Stacking the PRs would allow CI to pick up both PRs, which
is critical for ensuring that the dependent PR is correct.
This was considered for #155330, but the GitHub model for [stacking
PRs][2] required some work to be done ahead of #139632's creation
without the risk of confusing reviewers. Closing #139632 and opening a
new PR in service wasn't ideal, as it would have separated the PR
history from the PR that was ultimately merged.
**How this patch was tested**
Since this commit is a change to `__split_buffer_size_layout`, and needs
to be merged with `main` before #155330, this commit was cherry-picked
into #155330, and tested using the libc++ buildbot job for the unstable
ABI.
[1]: https://github.com/llvm/llvm-project/pull/139632/#discussion_r2282535795
[2]: https://llvm.org/docs/GitHub.html#stacked-pull-requests
---
libcxx/include/__split_buffer | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index da26a6e74935a..d6f479980961f 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -156,10 +156,8 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
- __split_buffer_pointer_layout<__split_buffer<value_type, allocator_type, __split_buffer_pointer_layout>,
- value_type,
- allocator_type>& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_without_allocator(__split_buffer_pointer_layout& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__back_cap_, __other.__back_cap_);
@@ -263,23 +261,19 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
- // Size-based __split_buffers track their size directly: we need to explicitly update the size
- // when the front is adjusted.
__begin_ = __new_begin;
__set_sentinel(__new_end);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
- // Size-based __split_buffers track their size directly: we need to explicitly update the size
- // when the front is adjusted.
__begin_ = __new_begin;
__set_sentinel(__new_size);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
_LIBCPP_ASSERT_INTERNAL(__front_cap_ <= __new_end, "__new_end cannot precede __front_cap_");
- __size_ += __new_end - end();
+ __size_ = __new_end - __begin_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __new_size) _NOEXCEPT {
>From 832fdb07056eeb03eade88e5f712d4ed82511c81 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 28 Jan 2026 02:41:51 +0000
Subject: [PATCH 13/39] reverts ranges.swap_ranges.pass.cpp
---
.../alg.swap/ranges.swap_ranges.pass.cpp | 54 +++++++++----------
1 file changed, 24 insertions(+), 30 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
index da42ce56db30a..85557ecbbfabc 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
@@ -67,6 +67,22 @@ TEST_CONSTEXPR_CXX20 void test_iterators() {
}
}
+template <std::size_t N>
+constexpr void test_vector_bool() {
+ { // Test swap_ranges() with aligned bytes
+ std::vector<bool> f(N, false), t(N, true);
+ std::ranges::swap_ranges(f, t);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
+ }
+ { // Test swap_ranges() with unaligned bytes
+ std::vector<bool> f(N, false), t(N + 8, true);
+ std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
+ }
+}
+
constexpr bool test() {
{ // Validate swapping ranges directly
std::array r1 = {1, 2, 3};
@@ -167,34 +183,15 @@ constexpr bool test() {
});
});
- return true;
-}
-
-// Test vector<bool>::iterator optimization
-template <std::size_t N>
-constexpr void test_vector_bool() {
- { // Test swap_ranges() with aligned bytes
- std::vector<bool> f(N, false), t(N, true);
- std::ranges::swap_ranges(f, t);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
+ { // Test vector<bool>::iterator optimization
+ test_vector_bool<8>();
+ test_vector_bool<19>();
+ test_vector_bool<32>();
+ test_vector_bool<49>();
+ test_vector_bool<64>();
+ test_vector_bool<199>();
+ test_vector_bool<256>();
}
- { // Test swap_ranges() with unaligned bytes
- std::vector<bool> f(N, false), t(N + 8, true);
- std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
- }
-}
-
-constexpr bool test_vector_bool() {
- test_vector_bool<8>();
- test_vector_bool<19>();
- test_vector_bool<32>();
- test_vector_bool<49>();
- test_vector_bool<64>();
- test_vector_bool<199>();
- test_vector_bool<256>();
return true;
}
@@ -204,8 +201,5 @@ int main(int, char**) {
test();
static_assert(test());
- test_vector_bool();
- static_assert(test_vector_bool());
-
return 0;
}
>From 10b2fc9615e75498d1b1dfd92ae92e596a4afdd9 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 28 Jan 2026 20:12:20 +0000
Subject: [PATCH 14/39] explicitly casts `__other` to `__base_type&`
---
libcxx/include/__split_buffer | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index d6f479980961f..89c398e525998 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -575,7 +575,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__swap_without_allocator(__split_buffer<value_type, allocator_type, _Layout>& __other) _NOEXCEPT {
- __base_type::__swap_without_allocator(__other);
+ __base_type::__swap_without_allocator(static_cast<__base_type&>(__other));
}
private:
>From 47cffb725b4966364a2d8fb1c7b187a21d7e6118 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Sat, 31 Jan 2026 02:37:33 +0000
Subject: [PATCH 15/39] reintroduces `__vector_layout`
This makes it much closer in design to ba94eeb. Further effort has gone
into reducing the diff with ToT.
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__vector/layout.h | 372 +++++++++++++
libcxx/include/__vector/vector.h | 502 ++++++------------
libcxx/include/module.modulemap.in | 1 +
.../alg.swap/ranges.swap_ranges.pass.cpp | 1 +
5 files changed, 546 insertions(+), 331 deletions(-)
create mode 100644 libcxx/include/__vector/layout.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 494c21bd30019..601371843c315 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -953,6 +953,7 @@ set(files
__vector/comparison.h
__vector/container_traits.h
__vector/erase.h
+ __vector/layout.h
__vector/pmr.h
__vector/swap.h
__vector/vector.h
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
new file mode 100644
index 0000000000000..c940d6e3469d5
--- /dev/null
+++ b/libcxx/include/__vector/layout.h
@@ -0,0 +1,372 @@
+//===----------------------------------------------------------------------===//
+//
+// 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___VECTOR_LAYOUT_H
+#define _LIBCPP___VECTOR_LAYOUT_H
+
+#include <__assert>
+#include <__config>
+#include <__memory/allocator_traits.h>
+#include <__memory/swap_allocator.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__utility/move.h>
+#include <__utility/swap.h>
+#include <__split_buffer>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+/// Defines `std::vector`'s storage layout and any operations that are affected by a change in the
+/// layout.
+///
+/// Dynamically-sized arrays like `std::vector` have several different representations. libc++
+/// supports two different layouts for `std::vector`:
+///
+/// * pointer-based layout
+/// * size-based layout
+//
+/// We describe these layouts below. All vector representations have a pointer that points to where
+/// the memory is allocated (called `__begin_`).
+///
+/// **Pointer-based layout**
+///
+/// The pointer-based layout uses two more pointers in addition to `__begin_`. The second pointer
+/// (called `__end_`) past the end of the part of the buffer that holds valid elements. The pointer
+/// (called `__capacity_`) points past the end of the allocated buffer. This is the default
+/// representation for libc++ due to historical reasons.
+///
+/// The second pointer has three primary use-cases:
+/// * to compute the size of the vector; and
+/// * to construct the past-the-end iterator; and
+/// * to indicate where the next element should be appended.
+///
+/// The third pointer is used to compute the capacity of the vector, which lets the vector know how
+/// many elements can be added to the vector before a reallocation is necessary.
+///
+/// __begin_ = 0xE4FD0, __end_ = 0xE4FF0, __capacity_ = 0xE5000
+/// 0xE4FD0 0xE4FF0 0xE5000
+/// ↓ ↓ ↓
+/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
+/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
+/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
+/// ↑ ↑ ↑
+/// __begin_ __end_ __capacity_
+///
+/// Figure 1: A visual representation of a pointer-based `std::vector<short>`. This vector has
+/// four elements, with the capacity to store six.
+///
+/// This is the default layout for libc++.
+///
+/// **Size-based layout**
+///
+/// The size-based layout uses integers to track its size and capacity, and computes pointers to
+/// past-the-end of the valid range and the whole buffer only when it's necessary. This layout is
+/// opt-in, but yields a significant performance boost relative to the pointer-based layout (see
+/// below).
+///
+/// __begin_ = 0xE4FD0, __size_ = 4, __capacity_ = 6
+/// 0xE4FD0
+/// ↓
+/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
+/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
+/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
+/// ↑
+/// __begin_
+///
+/// Figure 2: A visual representation of this a pointer-based layout. Blank boxes are not a part
+/// of the vector's allocated buffer. Boxes with numbers are valid elements within the vector,
+/// and boxes with `xx` have been allocated, but aren't being used as elements right now.
+//
+/// We conducted an extensive A/B test on production software to confirm that the size-based layout
+/// improves compute performance by 0.5%, and decreases system memory usage by up to 0.33%.
+///
+/// **Class design**
+///
+/// __vector_layout was designed with the following goals:
+/// 1. to abstractly represent the buffer's boundaries; and
+/// 2. to limit the number of `#ifdef` blocks that a reader needs to pass through; and
+/// 3. given (1) and (2), to have no logically identical components in multiple `#ifdef` clauses.
+///
+/// To facilitate these goals, there is a single `__vector_layout` definition. Users must choose
+/// their vector's layout when libc++ is being configured, so there we don't need to manage multiple
+/// vector layout types (e.g. `__vector_size_layout`, `__vector_pointer_layout`, etc.). In doing so,
+/// we reduce a significant portion of duplicate code.
+template <class _Tp, class _Allocator>
+class __vector_layout {
+public:
+ using value_type _LIBCPP_NODEBUG = _Tp;
+ using allocator_type _LIBCPP_NODEBUG = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using size_type _LIBCPP_NODEBUG = typename __alloc_traits::size_type;
+ using pointer _LIBCPP_NODEBUG = typename __alloc_traits::pointer;
+ using const_pointer _LIBCPP_NODEBUG = typename __alloc_traits::const_pointer;
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+ using __boundary_type _LIBCPP_NODEBUG = size_type;
+#else
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using __boundary_type _LIBCPP_NODEBUG = pointer;
+#endif
+
+ // Cannot be defaulted, since `_LIBCPP_COMPRESSED_PAIR` isn't an aggregate before C++14.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ __vector_layout() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __capacity_()
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit
+ __vector_layout(allocator_type const& __a) _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __capacity_()
+ , __alloc_(__a)
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ explicit __vector_layout(allocator_type&& __a) _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __capacity_()
+ , __alloc_(std::move(__a))
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other) _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_))
+ , __boundary_(std::move(__other.__boundary_))
+ , __capacity_(std::move(__other.__capacity_))
+ , __alloc_(std::move(__other.__alloc_))
+ {
+ __begin_ = nullptr;
+ __boundary_ = {};
+ __capacity_ = {};
+ }
+
+ /// Returns a reference to the stored allocator.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ allocator_type& __alloc() _NOEXCEPT {
+ return __alloc_;
+ }
+
+ /// Returns a reference to the stored allocator.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ allocator_type const& __alloc() const _NOEXCEPT {
+ return __alloc_;
+ }
+
+ /// Returns a pointer to the beginning of the buffer.
+ ///
+ /// `__begin_ptr()` is not called `data()` because `vector::data()` returns `T*`, but `__begin_`
+ /// is allowed to be a fancy pointer.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ pointer __begin_ptr() const _NOEXCEPT {
+ return __begin_;
+ }
+
+ /// Returns the value that the layout uses to determine the vector's size.
+ ///
+ /// `__boundary_representation()` should only be used when directly operating on the layout from
+ /// outside `__vector_layout`. Its result must be used with type deduction to avoid compile-time
+ /// failures.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ __boundary_type __boundary_representation() const _NOEXCEPT {
+ return __boundary_;
+ }
+
+ /// Returns the value that the layout uses to determine the vector's capacity.
+ ///
+ /// `__capacity_representation()` should only be used when directly operating on the layout from
+ /// outside `__vector_layout`. Its result must be used with type deduction to avoid compile-time
+ /// failures.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ __boundary_type __capacity_representation() const _NOEXCEPT {
+ return __capacity_;
+ }
+
+ /// Returns how many elements can be added before a reallocation occurs.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ size_type __remaining_capacity() const _NOEXCEPT {
+ return __capacity_ - __boundary_;
+ }
+
+ /// Determines if a reallocation is necessary.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ bool __is_full() const _NOEXCEPT {
+ return __boundary_ == __capacity_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __set_boundary(__size);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __set_boundary(__end);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void swap(__vector_layout& __other) _NOEXCEPT {
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__boundary_, __other.__boundary_);
+ std::swap(__capacity_, __other.__capacity_);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ // The following member functions must be implemented per vector layout.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp& back() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const& back() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_ptr() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(size_type __size) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __size) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __end) _NOEXCEPT;
+private:
+ pointer __begin_ = nullptr;
+ __boundary_type __boundary_{};
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ size_type __capacity_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
+#else
+ _LIBCPP_COMPRESSED_PAIR(pointer, __capacity_, allocator_type, __alloc_);
+#endif
+};
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT -> size_type {
+ return __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT -> size_type {
+ return __capacity_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT -> bool {
+ return __boundary_ == 0;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT -> _Tp& {
+ return __begin_[__boundary_ - 1];
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT -> _Tp const& {
+ return __begin_[__boundary_ - 1];
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT -> pointer {
+ return __begin_ + __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__invariants() const _NOEXCEPT {
+ if (__begin_ == nullptr)
+ return __boundary_ == 0 && __capacity_ == 0;
+ return !(__boundary_ > __capacity_);
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_boundary(size_type __n) _NOEXCEPT {
+ __boundary_ = __n;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_boundary(pointer __ptr) _NOEXCEPT {
+ __boundary_ = static_cast<size_type>(__ptr - __begin_);
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(size_type __n) _NOEXCEPT {
+ __capacity_ = __n;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(pointer __ptr) _NOEXCEPT {
+ __capacity_ = static_cast<size_type>(__ptr - __begin_);
+}
+#else
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT -> size_type {
+ return static_cast<size_type>(__boundary_ - __begin_);
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT -> size_type {
+ return static_cast<size_type>(__capacity_ - __begin_);
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT -> bool {
+ return __begin_ == __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT -> _Tp& {
+ return __boundary_[-1];
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT -> _Tp const& {
+ return __boundary_[-1];
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT -> pointer {
+ return __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__invariants() const _NOEXCEPT {
+ if (__begin_ == nullptr)
+ return __boundary_ == 0 && __capacity_ == 0;
+ if (__begin_ > __boundary_)
+ return false;
+ if (__begin_ == __capacity_)
+ return false;
+ return !(__boundary_ > __capacity_);
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_boundary(size_type __n) _NOEXCEPT {
+ __boundary_ = __begin_ + __n;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_boundary(pointer __ptr) _NOEXCEPT {
+ __boundary_ = __ptr;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(size_type __n) _NOEXCEPT {
+ __capacity_ = __begin_ + __n;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(pointer __ptr) _NOEXCEPT {
+ __capacity_ = __ptr;
+}
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___VECTOR_LAYOUT_H
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 990eeb66a2322..acb1ae854995e 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -73,6 +73,7 @@
// These headers define parts of vectors definition, since they define ADL functions or class specializations.
#include <__vector/comparison.h>
#include <__vector/container_traits.h>
+#include <__vector/layout.h>
#include <__vector/swap.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -85,21 +86,30 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
-#else
- using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
-#endif
+class vector : __vector_layout<_Tp, _Allocator> {
+ using __base_type _LIBCPP_NODEBUG = __vector_layout<_Tp, _Allocator>;
+ using __boundary_type _LIBCPP_NODEBUG = typename __base_type::__boundary_type;
+ using _SplitBuffer _LIBCPP_NODEBUG = typename __base_type::_SplitBuffer;
+
+ using __base_type::__alloc;
+ using __base_type::__begin_ptr;
+ using __base_type::__end_ptr;
+ using __base_type::__boundary_representation;
+ using __base_type::__capacity_representation;
+ using __base_type::__remaining_capacity;
+ using __base_type::__is_full;
+ using __base_type::__set_valid_range;
+ using __base_type::__set_boundary;
+ using __base_type::__set_capacity;
public:
//
// Types
//
using value_type = _Tp;
using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<_Allocator>;
+ using reference = _Tp&;
+ using const_reference = const _Tp&;
using size_type = typename __alloc_traits::size_type;
using difference_type = typename __alloc_traits::difference_type;
using pointer = typename __alloc_traits::pointer;
@@ -133,15 +143,14 @@ class vector {
//
// [vector.cons], construct/copy/destroy
//
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a)
#if _LIBCPP_STD_VER <= 14
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
#else
noexcept
#endif
- : __alloc_(__a) {
+ : __base_type(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -155,7 +164,7 @@ class vector {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base_type(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -177,7 +186,7 @@ class vector {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base_type(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -200,7 +209,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base_type(__a) {
__init_with_sentinel(__first, __last);
}
@@ -221,7 +230,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base_type(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -230,7 +239,7 @@ class vector {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __alloc_(__alloc) {
+ : __base_type(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -247,10 +256,10 @@ class vector {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__begin_ != nullptr) {
+ if (__vec_.__begin_ptr() != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_ptr(), __vec_.capacity());
}
}
@@ -262,13 +271,13 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) {
- __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
+ : __base_type(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) {
+ __init_with_size(__x.__begin_ptr(), __x.__end_ptr(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
+ : __base_type(__a) {
+ __init_with_size(__x.__begin_ptr(), __x.__end_ptr(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -279,7 +288,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base_type(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -342,23 +351,23 @@ class vector {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return this->__alloc_;
+ return this->__alloc();
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__end_pointer()));
+ return __make_iter(__add_alignment_assumption(__end_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__end_pointer()));
+ return __make_iter(__add_alignment_assumption(__end_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
@@ -392,32 +401,18 @@ class vector {
//
// [vector.capacity], capacity
//
-
- // Capacity
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __size_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __cap_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __size_ == 0;
- }
-#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(this->__end_ - this->__begin_);
+ return __base_type::size();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(this->__cap_ - this->__begin_);
+ return __base_type::capacity();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return this->__begin_ == this->__end_;
+ return __base_type::empty();
}
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__alloc()), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -427,62 +422,50 @@ class vector {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return this->__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return this->__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return this->__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return this->__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *this->__begin_ptr();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *this->__begin_ptr();
}
-
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
-#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base_type::back();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base_type::back();
}
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(this->__begin_ptr());
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(this->__begin_ptr());
}
//
@@ -505,7 +488,7 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -514,15 +497,15 @@ class vector {
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __len = ranges::distance(__range);
- if (__len < static_cast<difference_type>(__raw_capacity() - __raw_sentinel())) {
+ if (__len < static_cast<difference_type>(__remaining_capacity())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- _SplitBuffer __buffer(__recommend(size() + __len), size(), __alloc_);
+ _SplitBuffer __buffer(__recommend(size() + __len), size(), __alloc());
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
} else {
- vector __buffer(__alloc_);
+ vector __buffer(__alloc());
for (auto&& __val : __range)
__buffer.emplace_back(std::forward<decltype(__val)>(__val));
append_range(ranges::as_rvalue_view(__buffer));
@@ -532,7 +515,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
- this->__destruct_at_end(__end_pointer() - 1);
+ this->__destruct_at_end(__end_ptr() - 1);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x);
@@ -588,7 +571,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(this->__begin_);
+ __base_destruct_at_end(this->__begin_ptr());
__annotate_shrink(__old_size);
}
@@ -602,114 +585,8 @@ class vector {
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
#endif
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
-
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-
-private:
- using __sentinel_type _LIBCPP_NODEBUG = size_type;
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
- return __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __begin_ + __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __size_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __end - __begin_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
- __size_ = static_cast<size_type>(__pos - __begin_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
- __cap_ = static_cast<size_type>(__pos - __begin_);
- }
-
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- [[no_unique_address]] allocator_type __alloc_;
-#else
-
+ using __base_type::__invariants;
private:
- using __sentinel_type _LIBCPP_NODEBUG = pointer;
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __end_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __end;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __begin_ + __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
- __end_ = __begin_ + __offset;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
- __cap_ = __begin_ + __offset;
- }
-
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20
- _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
- return __cap_;
- }
-
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
@@ -722,7 +599,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(this->__alloc_, __n);
+ auto __allocation = std::__allocate_at_least(this->__alloc(), __n);
__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__set_capacity(__allocation.count);
__annotate_new(0);
@@ -773,7 +650,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, *__first);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc(), *__first);
*__position = std::move(__tmp.get());
}
}
@@ -811,8 +688,8 @@ class vector {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(this->__begin_),
- std::__wrap_iter<pointer>(__raw_capacity()));
+ std::__wrap_iter<pointer>(this->__begin_ptr()),
+ std::__wrap_iter<pointer>(__capacity_representation()));
#else
return iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -823,8 +700,8 @@ class vector {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(this->__begin_),
- std::__wrap_iter<const_pointer>(__raw_capacity()));
+ std::__wrap_iter<const_pointer>(this->__begin_ptr()),
+ std::__wrap_iter<const_pointer>(__capacity_representation()));
#else
return const_iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -847,7 +724,7 @@ class vector {
}
template <class... _Args>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline __sentinel_type
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline __boundary_type
__emplace_back_slow_path(_Args&&... __args);
// The following functions are no-ops outside of AddressSanitizer mode.
@@ -881,14 +758,14 @@ class vector {
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
- : __v_(__v), __pos_(__v.__end_pointer()), __new_end_(__pos_ + __n) {
+ : __v_(__v), __pos_(__v.__end_ptr()), __new_end_(__pos_ + __n) {
__v_.__annotate_increase(__n);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __v_.__set_sentinel(__pos_);
+ __v_.__set_boundary(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__begin_);
+ __v_.__annotate_shrink(__new_end_ - __v_.__begin_ptr());
}
}
@@ -901,10 +778,10 @@ class vector {
};
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
- pointer __soon_to_be_end = __end_pointer();
+ pointer __soon_to_be_end = __end_ptr();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end));
- __set_sentinel(__new_last);
+ __alloc_traits::destroy(this->__alloc(), std::__to_address(--__soon_to_be_end));
+ __set_boundary(__new_last);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {
@@ -922,21 +799,21 @@ class vector {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (this->__alloc() != __c.__alloc()) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc(), this->__begin_ptr(), capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
- __set_capacity(static_cast<__sentinel_type>(0));
+ __set_capacity(static_cast<__boundary_type>(0));
}
- this->__alloc_ = __c.__alloc_;
+ this->__alloc() = __c.__alloc();
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- this->__alloc_ = std::move(__c.__alloc_);
+ this->__alloc() = std::move(__c.__alloc());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -958,9 +835,9 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__swap_layouts(_SplitBuffer& __sb) {
- auto __vector_begin = __begin_;
- auto __vector_sentinel = __raw_sentinel();
- auto __vector_cap = __raw_capacity();
+ auto __vector_begin = __begin_ptr();
+ auto __vector_boundary = __boundary_representation();
+ auto __vector_cap = __capacity_representation();
auto __sb_begin = __sb.begin();
auto __sb_sentinel = __sb.__raw_sentinel();
@@ -969,7 +846,7 @@ class vector {
__set_valid_range(__sb_begin, __sb_sentinel);
__set_capacity(__sb_cap);
- __sb.__set_valid_range(__vector_begin, __vector_sentinel);
+ __sb.__set_valid_range(__vector_begin, __vector_boundary);
__sb.__set_capacity(__vector_cap);
}
};
@@ -995,7 +872,7 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__begin_, size()) into the front of __v and swaps the
+// __swap_out_circular_buffer relocates the objects in [__begin_ptr(), size()) into the front of __v and swaps the
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
@@ -1004,19 +881,19 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_pointer()), std::__to_address(__new_begin));
+ this->__alloc(), std::__to_address(__begin_ptr()), std::__to_address(__end_ptr()), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
- __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
+// __swap_out_circular_buffer relocates the objects in [__begin_ptr(), __p) into the front of __v, the objects in
// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __begin_) objects in the front and space for at least (size() - __p) objects in the back. This
-// function has a strong exception guarantee if __begin_ == __p || size() == __p.
+// exactly (__p - __begin_ptr()) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __begin_ptr() == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
@@ -1024,21 +901,21 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
__annotate_delete();
pointer __ret = __v.begin();
- pointer __end = __end_pointer();
- // Relocate [__p, __end) first to avoid having a hole in [__begin_, __end)
- // in case something in [__begin_, __p) throws.
+ pointer __end = __end_ptr();
+ // Relocate [__p, __end) first to avoid having a hole in [__begin_ptr(), __end)
+ // in case something in [__begin_ptr(), __p) throws.
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ this->__alloc(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
- __set_sentinel(
- __raw_sentinel() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __begin_);
+ __set_boundary(
+ __boundary_representation() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
+ auto __new_begin = __v.begin() - (__p - __begin_ptr());
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
+ this->__alloc(), std::__to_address(__begin_ptr()), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
- __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
__swap_layouts(__v);
__v.__set_data(__v.begin());
@@ -1048,10 +925,10 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (this->__begin_ != nullptr) {
+ if (this->__begin_ptr() != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc(), this->__begin_ptr(), capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<size_type>(0));
}
@@ -1070,7 +947,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
return std::max<size_type>(2 * __cap, __new_size);
}
-// Default constructs __n objects starting at __end_pointer()
+// Default constructs __n objects starting at __end_ptr()
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -1080,11 +957,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_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->__alloc_, std::__to_address(__pos));
+ __alloc_traits::construct(this->__alloc(), std::__to_address(__pos));
}
}
-// Copy constructs __n objects starting at __end_pointer() from __x
+// Copy constructs __n objects starting at __end_ptr() from __x
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -1096,7 +973,7 @@ 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->__alloc_, std::__to_address(__pos), __x);
+ __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), __x);
}
}
@@ -1105,7 +982,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1115,9 +992,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __alloc_(std::move(__x.__alloc_)) {
- __set_valid_range(__x.__begin_, __x.__raw_sentinel());
- __set_capacity(__x.__raw_capacity());
+ : __base_type(std::move(__x.__alloc())) {
+ __set_valid_range(__x.__begin_ptr(), __x.__boundary_representation());
+ __set_capacity(__x.__capacity_representation());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
}
@@ -1125,10 +1002,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- if (__a == __x.__alloc_) {
- __set_valid_range(__x.__begin_, __x.__raw_sentinel());
- __set_capacity(__x.__raw_capacity());
+ : __base_type(__a) {
+ if (__a == __x.__alloc()) {
+ __set_valid_range(__x.__begin_ptr(), __x.__boundary_representation());
+ __set_capacity(__x.__capacity_representation());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
} else {
@@ -1140,7 +1017,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (this->__alloc() != __c.__alloc()) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1152,8 +1029,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- __set_valid_range(__c.__begin_, __c.__raw_sentinel());
- __set_capacity(__c.__raw_capacity());
+ __set_valid_range(__c.__begin_ptr(), __c.__boundary_representation());
+ __set_capacity(__c.__capacity_representation());
__c.__set_valid_range(nullptr, static_cast<size_type>(0));
__c.__set_capacity(static_cast<size_type>(0));
}
@@ -1163,7 +1040,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__begin_, __x.__end_pointer());
+ assign(__x.__begin_ptr(), __x.__end_ptr());
}
return *this;
}
@@ -1172,8 +1049,8 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __begin_;
- pointer __end = __end_pointer();
+ pointer __cur = __begin_ptr();
+ pointer __end = __end_ptr();
for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
if (__cur != __end) {
@@ -1192,10 +1069,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
auto const __size = size();
if (__new_size > __size) {
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_ptr()).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
+ pointer __m = std::__copy(std::move(__first), __last, this->__begin_ptr()).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1209,11 +1086,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(this->__begin_, std::min(__n, __s), __u);
+ std::fill_n(this->__begin_ptr(), std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(this->__begin_ + __n);
+ this->__destruct_at_end(this->__begin_ptr() + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1226,7 +1103,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- _SplitBuffer __v(__n, size(), this->__alloc_);
+ _SplitBuffer __v(__n, size(), this->__alloc());
__swap_out_circular_buffer(__v);
}
}
@@ -1237,7 +1114,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- _SplitBuffer __v(size(), size(), this->__alloc_);
+ _SplitBuffer __v(size(), size(), this->__alloc());
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1252,15 +1129,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
template <class _Tp, class _Allocator>
template <class... _Args>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__boundary_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- _SplitBuffer __v(__recommend(size() + 1), size(), this->__alloc_);
+ _SplitBuffer __v(__recommend(size() + 1), size(), this->__alloc());
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc(), std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
- return __raw_sentinel();
+ return __boundary_representation();
}
// This makes the compiler inline `__else()` if `__cond` is known to be false. Currently LLVM doesn't do that without
@@ -1290,16 +1167,16 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
- auto __current_sentinel = __raw_sentinel();
+ auto __current_boundary = __boundary_representation();
std::__if_likely_else(
- __current_sentinel < __raw_capacity(),
+ __current_boundary < __capacity_representation(),
[&] {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
- ++__current_sentinel;
+ ++__current_boundary;
},
- [&] { __current_sentinel = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
+ [&] { __current_boundary = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
- __set_sentinel(__current_sentinel);
+ __set_boundary(__current_boundary);
#if _LIBCPP_STD_VER >= 17
return back();
#endif
@@ -1311,8 +1188,8 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = this->__begin_ + __ps;
- this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
+ pointer __p = this->__begin_ptr() + __ps;
+ this->__destruct_at_end(std::move(__p + 1, __end_ptr(), __p));
return __make_iter(__p);
}
@@ -1320,9 +1197,9 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = this->__begin_ + (__first - begin());
+ pointer __p = this->__begin_ptr() + (__first - begin());
if (__first != __last) {
- this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
+ this->__destruct_at_end(std::move(__p + (__last - __first), __end_ptr(), __p));
}
return __make_iter(__p);
}
@@ -1330,13 +1207,13 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
- pointer __old_last = __end_pointer();
+ pointer __old_last = __end_ptr();
difference_type __n = __old_last - __to;
{
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->__alloc_, std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1345,9 +1222,9 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = this->__begin_ptr() + (__position - begin());
if (!__is_full()) {
- pointer __end = __end_pointer();
+ pointer __end = __end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(__x);
} else {
@@ -1359,7 +1236,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
}
} else {
_SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1369,9 +1246,9 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = this->__begin_ptr() + (__position - begin());
if (!__is_full()) {
- pointer __end = __end_pointer();
+ pointer __end = __end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(std::move(__x));
} else {
@@ -1380,7 +1257,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
}
} else {
_SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1391,19 +1268,19 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = this->__begin_ptr() + (__position - begin());
if (!__is_full()) {
- pointer __end = __end_pointer();
+ pointer __end = __end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc(), std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
_SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1413,11 +1290,11 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = this->__begin_ptr() + (__position - begin());
if (__n > 0) {
if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
- pointer __end = __end_pointer();
+ pointer __end = __end_ptr();
pointer __old_last = __end;
if (__n > static_cast<size_type>(__end - __p)) {
size_type __cx = __n - (__end - __p);
@@ -1433,7 +1310,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
}
} else {
_SplitBuffer __v(
- __recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1446,29 +1323,29 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = this->__begin_ + __off;
- pointer __old_last = __end_pointer();
+ pointer __p = this->__begin_ptr() + __off;
+ pointer __old_last = __end_ptr();
for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
if (__first == __last)
- (void)std::rotate(__p, __old_last, __end_pointer());
+ (void)std::rotate(__p, __old_last, __end_ptr());
else {
- _SplitBuffer __v(__alloc_);
- pointer __end = __end_pointer();
+ _SplitBuffer __v(__alloc());
+ pointer __end = __end_ptr();
auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, __end));
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc(), __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
_SplitBuffer __merged(
- __recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
+ __recommend(size() + __v.size()), __off, __alloc()); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__old_last), std::__to_address(__end_pointer()), std::__to_address(__merged.end()));
- __guard.__complete(); // Release the guard once objects in [__old_last_, __end_pointer()) have been successfully
+ __alloc(), std::__to_address(__old_last), std::__to_address(__end_ptr()), std::__to_address(__merged.end()));
+ __guard.__complete(); // Release the guard once objects in [__old_last_, __end_ptr()) have been successfully
// relocated.
- __merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
- __set_sentinel(__old_last);
+ __merged.__set_sentinel(__merged.end() + (__end_ptr() - __old_last));
+ __set_boundary(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __alloc(), std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1481,10 +1358,10 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = this->__begin_ptr() + (__position - begin());
if (__n > 0) {
if (__n <= static_cast<difference_type>(__remaining_capacity())) {
- pointer __end = __end_pointer();
+ pointer __end = __end_ptr();
pointer __old_last = __end;
difference_type __dx = __end - __p;
if (__n > __dx) {
@@ -1508,7 +1385,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
}
} else {
_SplitBuffer __v(
- __recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1523,12 +1400,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc_);
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc());
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ptr() + __new_size);
}
}
@@ -1539,12 +1416,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc_);
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc());
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ptr() + __new_size);
}
}
@@ -1557,48 +1434,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
#endif
{
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ __alloc_traits::propagate_on_container_swap::value || __alloc() == __x.__alloc(),
"vector::swap: Either propagate_on_container_swap must be true"
" or the allocators must compare equal");
- std::swap(this->__begin_, __x.__begin_);
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- std::swap(this->__size_, __x.__size_);
-#else
- std::swap(this->__end_, __x.__end_);
-#endif
- std::swap(this->__cap_, __x.__cap_);
- std::__swap_allocator(this->__alloc_, __x.__alloc_);
-}
-
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
- if (__begin_ == nullptr) {
- if (__size_ != 0 || __cap_ != 0)
- return false;
- } else {
- if (__size_ > __cap_)
- return false;
- }
- return true;
-}
-#else
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
- if (this->__begin_ == nullptr) {
- if (this->__end_ != nullptr || this->__cap_ != nullptr)
- return false;
- } else {
- if (this->__begin_ > this->__end_)
- return false;
- if (this->__begin_ == this->__cap_)
- return false;
- if (this->__end_ > this->__cap_)
- return false;
- }
- return true;
+ __base_type::swap(static_cast<__base_type&>(__x));
}
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
#if _LIBCPP_STD_VER >= 20
template <>
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 58fc4941cb7d8..dae4ce652f38c 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2224,6 +2224,7 @@ module std [system] {
export std.format.formatter
}
+ module layout { header "__vector/layout.h" }
module pmr {
header "__vector/pmr.h"
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
index 85557ecbbfabc..f188a636d8254 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
@@ -9,6 +9,7 @@
// <algorithm>
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=9000000
// template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2>
// requires indirectly_swappable<I1, I2>
>From 9e036bde1367ee0b1e8a0a33ea9cf498d060a065 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 07:50:25 +0000
Subject: [PATCH 16/39] limits how often vector needs to manually set
`__vector_layout`
---
libcxx/include/__split_buffer | 17 ++++++++++++++++
libcxx/include/__vector/layout.h | 22 ++++++++++++++++++---
libcxx/include/__vector/vector.h | 33 ++++++--------------------------
3 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 89c398e525998..46c72e387f215 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -188,6 +188,14 @@ public:
__back_cap_ = __other.__back_cap_;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __swap_layouts(pointer& __begin, pointer& __end, pointer& __back_capacity)
+ {
+ std::swap(__begin_, __begin);
+ std::swap(__end_, __end);
+ std::swap(__back_cap_, __back_capacity);
+ }
+
private:
pointer __front_cap_ = nullptr;
pointer __begin_ = nullptr;
@@ -336,6 +344,14 @@ public:
__size_ = __other.__size_;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __swap_layouts(pointer& __begin, size_type& __size, size_type& __capacity)
+ {
+ std::swap(__begin_, __begin);
+ std::swap(__size_, __size);
+ std::swap(__cap_, __capacity);
+ }
+
private:
pointer __front_cap_ = nullptr;
pointer __begin_ = nullptr;
@@ -447,6 +463,7 @@ public:
using __base_type::__set_data;
using __base_type::__set_sentinel;
using __base_type::__set_valid_range;
+ using __base_type::__swap_layouts;
using typename __base_type::__alloc_traits;
using typename __base_type::allocator_type;
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index c940d6e3469d5..7cd8c7744df43 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -143,9 +143,9 @@ class __vector_layout {
, __capacity_(std::move(__other.__capacity_))
, __alloc_(std::move(__other.__alloc_))
{
- __begin_ = nullptr;
- __boundary_ = {};
- __capacity_ = {};
+ __other.__begin_ = nullptr;
+ __other.__boundary_ = {};
+ __other.__capacity_ = {};
}
/// Returns a reference to the stored allocator.
@@ -221,6 +221,22 @@ class __vector_layout {
std::__swap_allocator(__alloc_, __other.__alloc_);
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __swap_layouts(_SplitBuffer& __other) _NOEXCEPT {
+ __other.__swap_layouts(__begin_, __boundary_, __capacity_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
+ void __move_layout(__vector_layout& __other) _NOEXCEPT {
+ __begin_ = __other.__begin_;
+ __boundary_ = __other.__boundary_;
+ __capacity_ = __other.__capacity_;
+
+ __other.__begin_ = nullptr;
+ __other.__boundary_ = {};
+ __other.__capacity_ = {};
+ }
+
// The following member functions must be implemented per vector layout.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT;
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index acb1ae854995e..7dd4f3a2b0c67 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -98,9 +98,11 @@ class vector : __vector_layout<_Tp, _Allocator> {
using __base_type::__capacity_representation;
using __base_type::__remaining_capacity;
using __base_type::__is_full;
+ using __base_type::__move_layout;
using __base_type::__set_valid_range;
using __base_type::__set_boundary;
using __base_type::__set_capacity;
+ using __base_type::__swap_layouts;
public:
//
// Types
@@ -689,7 +691,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
std::__wrap_iter<pointer>(this->__begin_ptr()),
- std::__wrap_iter<pointer>(__capacity_representation()));
+ std::__wrap_iter<pointer>(this->__capacity_ptr()));
#else
return iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -701,7 +703,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
std::__wrap_iter<const_pointer>(this->__begin_ptr()),
- std::__wrap_iter<const_pointer>(__capacity_representation()));
+ std::__wrap_iter<const_pointer>(this->__capacity_ptr()));
#else
return const_iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -832,23 +834,6 @@ class vector : __vector_layout<_Tp, _Allocator> {
__add_alignment_assumption(_Ptr __p) _NOEXCEPT {
return __p;
}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_layouts(_SplitBuffer& __sb) {
- auto __vector_begin = __begin_ptr();
- auto __vector_boundary = __boundary_representation();
- auto __vector_cap = __capacity_representation();
-
- auto __sb_begin = __sb.begin();
- auto __sb_sentinel = __sb.__raw_sentinel();
- auto __sb_cap = __sb.__raw_capacity();
-
- __set_valid_range(__sb_begin, __sb_sentinel);
- __set_capacity(__sb_cap);
-
- __sb.__set_valid_range(__vector_begin, __vector_boundary);
- __sb.__set_capacity(__vector_cap);
- }
};
#if _LIBCPP_STD_VER >= 17
@@ -1004,10 +989,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
: __base_type(__a) {
if (__a == __x.__alloc()) {
- __set_valid_range(__x.__begin_ptr(), __x.__boundary_representation());
- __set_capacity(__x.__capacity_representation());
- __x.__set_valid_range(nullptr, static_cast<size_type>(0));
- __x.__set_capacity(static_cast<size_type>(0));
+ __move_layout(static_cast<__base_type&>(__x));
} else {
typedef move_iterator<iterator> _Ip;
__init_with_size(_Ip(__x.begin()), _Ip(__x.end()), __x.size());
@@ -1029,10 +1011,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- __set_valid_range(__c.__begin_ptr(), __c.__boundary_representation());
- __set_capacity(__c.__capacity_representation());
- __c.__set_valid_range(nullptr, static_cast<size_type>(0));
- __c.__set_capacity(static_cast<size_type>(0));
+ __move_layout(static_cast<__base_type&>(__c));
}
template <class _Tp, class _Allocator>
>From f82221e0dcfd168de994452409dbf6dab9fa9c9b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 07:51:21 +0000
Subject: [PATCH 17/39] teaches GDB how to use the new vector layout
---
libcxx/utils/gdb/libcxx/printers.py | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 83df6be78a1bb..e03c9ba9a7dc2 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -351,28 +351,38 @@ def __init__(self, val):
"""Set val, length, capacity, and iterator for bool and normal vectors."""
self.val = val
self.typename = _remove_generics(_prettify_typename(val.type))
- begin = self.val["__begin_"]
if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
self.typename += "<bool>"
+ begin = self.val["__begin_"]
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- cap = self.val["__cap_"]
+ for i in self.val.type.fields():
+ if i.is_base_class:
+ base = val[i]
+ break
+
+ begin = base["__begin_"]
+ if self.val.type.fields()[0].is_base_class:
+ boundary = base["__boundary_"]
+ capacity = base["__capacity_"]
+ else:
+ boundary = base["__end_"]
+ capacity = base["__cap_"]
# We test for integers because `vector<T>::size_type` is required to
# be an unsigned integer, whereas `vector<T>::pointer` can be any
# type that satisfies the Cpp17NullablePointer requirements.
- if cap.type.strip_typedefs().code == gdb.TYPE_CODE_INT:
- size = self.val["__size_"]
- self.length = size
- self.capacity = cap
- end = begin + size
+ if boundary.type.strip_typedefs().code == gdb.TYPE_CODE_INT:
+ self.length = boundary
+ self.capacity = capacity
+ end = begin + boundary
else:
- end = self.val["__end_"]
+ end = boundary
self.length = end - begin
- self.capacity = cap - begin
+ self.capacity = capacity - begin
self.iterator = self._VectorIterator(begin, end)
>From f9f09ebce938bf2ccd76bc69febb705037f4e492 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 08:02:25 +0000
Subject: [PATCH 18/39] adds missing compressed_pair.h
---
libcxx/include/__vector/layout.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 7cd8c7744df43..387798ad61143 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -12,6 +12,7 @@
#include <__assert>
#include <__config>
#include <__memory/allocator_traits.h>
+#include <__memory/compressed_pair.h>
#include <__memory/swap_allocator.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__utility/move.h>
>From eb8fc0c791002d8fe5e1112ae60f55821ed89dba Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 08:04:24 +0000
Subject: [PATCH 19/39] runs clang-format
---
libcxx/include/__split_buffer | 10 +++----
libcxx/include/__vector/vector.h | 48 +++++++++++++++-----------------
2 files changed, 27 insertions(+), 31 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 46c72e387f215..1332f89c078fc 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -188,9 +188,8 @@ public:
__back_cap_ = __other.__back_cap_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __swap_layouts(pointer& __begin, pointer& __end, pointer& __back_capacity)
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_layouts(pointer& __begin, pointer& __end, pointer& __back_capacity) {
std::swap(__begin_, __begin);
std::swap(__end_, __end);
std::swap(__back_cap_, __back_capacity);
@@ -344,9 +343,8 @@ public:
__size_ = __other.__size_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __swap_layouts(pointer& __begin, size_type& __size, size_type& __capacity)
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_layouts(pointer& __begin, size_type& __size, size_type& __capacity) {
std::swap(__begin_, __begin);
std::swap(__size_, __size);
std::swap(__cap_, __capacity);
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 7dd4f3a2b0c67..b908dc443e5ea 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -87,22 +87,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector : __vector_layout<_Tp, _Allocator> {
- using __base_type _LIBCPP_NODEBUG = __vector_layout<_Tp, _Allocator>;
+ using __base_type _LIBCPP_NODEBUG = __vector_layout<_Tp, _Allocator>;
using __boundary_type _LIBCPP_NODEBUG = typename __base_type::__boundary_type;
- using _SplitBuffer _LIBCPP_NODEBUG = typename __base_type::_SplitBuffer;
+ using _SplitBuffer _LIBCPP_NODEBUG = typename __base_type::_SplitBuffer;
using __base_type::__alloc;
using __base_type::__begin_ptr;
- using __base_type::__end_ptr;
using __base_type::__boundary_representation;
using __base_type::__capacity_representation;
- using __base_type::__remaining_capacity;
+ using __base_type::__end_ptr;
using __base_type::__is_full;
using __base_type::__move_layout;
- using __base_type::__set_valid_range;
+ using __base_type::__remaining_capacity;
using __base_type::__set_boundary;
using __base_type::__set_capacity;
+ using __base_type::__set_valid_range;
using __base_type::__swap_layouts;
+
public:
//
// Types
@@ -588,6 +589,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
#endif
using __base_type::__invariants;
+
private:
// Allocate space for __n objects
// throws length_error if __n > max_size()
@@ -709,8 +711,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(_SplitBuffer& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(_SplitBuffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
__swap_out_circular_buffer(_SplitBuffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
@@ -861,12 +862,14 @@ vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc(), std::__to_address(__begin_ptr()), std::__to_address(__end_ptr()), std::__to_address(__new_begin));
+ this->__alloc(),
+ std::__to_address(__begin_ptr()),
+ std::__to_address(__end_ptr()),
+ std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
__set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
@@ -881,8 +884,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
// function has a strong exception guarantee if __begin_ptr() == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
- pointer __p) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v, pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
@@ -893,8 +895,8 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v,
this->__alloc(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
- __set_boundary(
- __boundary_representation() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
+ __set_boundary(__boundary_representation() -
+ __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
auto __new_begin = __v.begin() - (__p - __begin_ptr());
std::__uninitialized_allocator_relocate(
@@ -967,7 +969,8 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ =
+ std::__uninitialized_allocator_copy(this->__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1214,8 +1217,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- _SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1235,8 +1237,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- _SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1258,8 +1259,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
*__p = std::move(__tmp.get());
}
} else {
- _SplitBuffer __v(
- __recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1288,8 +1288,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- _SplitBuffer __v(
- __recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1363,8 +1362,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- _SplitBuffer __v(
- __recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
>From 4343a5920d1b2aaf0272325cb4c916832321caab Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 08:17:33 +0000
Subject: [PATCH 20/39] fixes formatting issues flagged by CI
---
libcxx/include/__vector/layout.h | 111 ++++++++++++++-----------------
1 file changed, 50 insertions(+), 61 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 387798ad61143..e9970016770e3 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -14,10 +14,10 @@
#include <__memory/allocator_traits.h>
#include <__memory/compressed_pair.h>
#include <__memory/swap_allocator.h>
+#include <__split_buffer>
#include <__type_traits/is_nothrow_constructible.h>
#include <__utility/move.h>
#include <__utility/swap.h>
-#include <__split_buffer>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -57,11 +57,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
///
/// __begin_ = 0xE4FD0, __end_ = 0xE4FF0, __capacity_ = 0xE5000
/// 0xE4FD0 0xE4FF0 0xE5000
-/// ↓ ↓ ↓
+/// v v v
/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
-/// ↑ ↑ ↑
+/// ^ ^ ^
/// __begin_ __end_ __capacity_
///
/// Figure 1: A visual representation of a pointer-based `std::vector<short>`. This vector has
@@ -78,11 +78,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
///
/// __begin_ = 0xE4FD0, __size_ = 4, __capacity_ = 6
/// 0xE4FD0
-/// ↓
+/// v
/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
-/// ↑
+/// ^
/// __begin_
///
/// Figure 2: A visual representation of this a pointer-based layout. Blank boxes are not a part
@@ -106,58 +106,52 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator>
class __vector_layout {
public:
- using value_type _LIBCPP_NODEBUG = _Tp;
+ using value_type _LIBCPP_NODEBUG = _Tp;
using allocator_type _LIBCPP_NODEBUG = _Allocator;
using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using size_type _LIBCPP_NODEBUG = typename __alloc_traits::size_type;
- using pointer _LIBCPP_NODEBUG = typename __alloc_traits::pointer;
- using const_pointer _LIBCPP_NODEBUG = typename __alloc_traits::const_pointer;
+ using size_type _LIBCPP_NODEBUG = typename __alloc_traits::size_type;
+ using pointer _LIBCPP_NODEBUG = typename __alloc_traits::pointer;
+ using const_pointer _LIBCPP_NODEBUG = typename __alloc_traits::const_pointer;
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
using __boundary_type _LIBCPP_NODEBUG = size_type;
#else
- using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using _SplitBuffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
using __boundary_type _LIBCPP_NODEBUG = pointer;
#endif
// Cannot be defaulted, since `_LIBCPP_COMPRESSED_PAIR` isn't an aggregate before C++14.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- __vector_layout() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __capacity_()
- {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit
- __vector_layout(allocator_type const& __a) _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __capacity_()
- , __alloc_(__a)
- {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- explicit __vector_layout(allocator_type&& __a) _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __capacity_()
- , __alloc_(std::move(__a))
- {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other) _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __begin_(std::move(__other.__begin_))
- , __boundary_(std::move(__other.__boundary_))
- , __capacity_(std::move(__other.__capacity_))
- , __alloc_(std::move(__other.__alloc_))
- {
- __other.__begin_ = nullptr;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __capacity_() {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
+ _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __capacity_(), __alloc_(__a) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __capacity_(), __alloc_(std::move(__a)) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_)),
+ __boundary_(std::move(__other.__boundary_)),
+ __capacity_(std::move(__other.__capacity_)),
+ __alloc_(std::move(__other.__alloc_)) {
+ __other.__begin_ = nullptr;
__other.__boundary_ = {};
__other.__capacity_ = {};
}
/// Returns a reference to the stored allocator.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- allocator_type& __alloc() _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT {
return __alloc_;
}
/// Returns a reference to the stored allocator.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- allocator_type const& __alloc() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
+ __alloc() const _NOEXCEPT {
return __alloc_;
}
@@ -165,8 +159,7 @@ class __vector_layout {
///
/// `__begin_ptr()` is not called `data()` because `vector::data()` returns `T*`, but `__begin_`
/// is allowed to be a fancy pointer.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- pointer __begin_ptr() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __begin_ptr() const _NOEXCEPT {
return __begin_;
}
@@ -175,8 +168,8 @@ class __vector_layout {
/// `__boundary_representation()` should only be used when directly operating on the layout from
/// outside `__vector_layout`. Its result must be used with type deduction to avoid compile-time
/// failures.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- __boundary_type __boundary_representation() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __boundary_type
+ __boundary_representation() const _NOEXCEPT {
return __boundary_;
}
@@ -185,55 +178,50 @@ class __vector_layout {
/// `__capacity_representation()` should only be used when directly operating on the layout from
/// outside `__vector_layout`. Its result must be used with type deduction to avoid compile-time
/// failures.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- __boundary_type __capacity_representation() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __boundary_type
+ __capacity_representation() const _NOEXCEPT {
return __capacity_;
}
/// Returns how many elements can be added before a reallocation occurs.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- size_type __remaining_capacity() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
return __capacity_ - __boundary_;
}
/// Determines if a reallocation is necessary.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- bool __is_full() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
return __boundary_ == __capacity_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
__begin_ = __begin;
__set_boundary(__size);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
__begin_ = __begin;
__set_boundary(__end);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void swap(__vector_layout& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __other) _NOEXCEPT {
std::swap(__begin_, __other.__begin_);
std::swap(__boundary_, __other.__boundary_);
std::swap(__capacity_, __other.__capacity_);
std::__swap_allocator(__alloc_, __other.__alloc_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __swap_layouts(_SplitBuffer& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(_SplitBuffer& __other) _NOEXCEPT {
__other.__swap_layouts(__begin_, __boundary_, __capacity_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- void __move_layout(__vector_layout& __other) _NOEXCEPT {
- __begin_ = __other.__begin_;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_layout(__vector_layout& __other) _NOEXCEPT {
+ __begin_ = __other.__begin_;
__boundary_ = __other.__boundary_;
__capacity_ = __other.__capacity_;
- __other.__begin_ = nullptr;
+ __other.__begin_ = nullptr;
__other.__boundary_ = {};
__other.__capacity_ = {};
}
@@ -250,6 +238,7 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __size) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __end) _NOEXCEPT;
+
private:
pointer __begin_ = nullptr;
__boundary_type __boundary_{};
>From ebbe89432ae9ee2de82f1660bd936a7d7d7a492a Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 2 Feb 2026 21:15:27 +0000
Subject: [PATCH 21/39] fixes C++03 and relevant GCC failures
---
libcxx/include/__vector/layout.h | 41 +++++++++++++++++++-------------
libcxx/include/__vector/vector.h | 5 ++--
2 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index e9970016770e3..1133bb1e79c99 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -140,8 +140,8 @@ class __vector_layout {
__capacity_(std::move(__other.__capacity_)),
__alloc_(std::move(__other.__alloc_)) {
__other.__begin_ = nullptr;
- __other.__boundary_ = {};
- __other.__capacity_ = {};
+ __other.__boundary_ = __boundary_type();
+ __other.__capacity_ = __boundary_type();
}
/// Returns a reference to the stored allocator.
@@ -222,8 +222,8 @@ class __vector_layout {
__capacity_ = __other.__capacity_;
__other.__begin_ = nullptr;
- __other.__boundary_ = {};
- __other.__capacity_ = {};
+ __other.__boundary_ = __boundary_type();
+ __other.__capacity_ = __boundary_type();
}
// The following member functions must be implemented per vector layout.
@@ -241,44 +241,48 @@ class __vector_layout {
private:
pointer __begin_ = nullptr;
- __boundary_type __boundary_{};
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ size_type __boundary_ = 0;
size_type __capacity_ = 0;
[[no_unique_address]] allocator_type __alloc_;
#else
+ pointer __boundary_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __capacity_, allocator_type, __alloc_);
#endif
};
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT -> size_type {
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT {
return __boundary_;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT -> size_type {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::size_type
+__vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT {
return __capacity_;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT -> bool {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT {
return __boundary_ == 0;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT -> _Tp& {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT {
return __begin_[__boundary_ - 1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT -> _Tp const& {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT {
return __begin_[__boundary_ - 1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT -> pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __begin_ + __boundary_;
}
@@ -310,32 +314,35 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
}
#else
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT -> size_type {
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT {
return static_cast<size_type>(__boundary_ - __begin_);
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT -> size_type {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::size_type
+__vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT {
return static_cast<size_type>(__capacity_ - __begin_);
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT -> bool {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT {
return __begin_ == __boundary_;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT -> _Tp& {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT {
return __boundary_[-1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT -> _Tp const& {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT {
return __boundary_[-1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 auto __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT -> pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __boundary_;
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index b908dc443e5ea..8546e7cc38d06 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -240,9 +240,8 @@ class vector : __vector_layout<_Tp, _Allocator> {
#if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<_Tp> _Range>
- _LIBCPP_HIDE_FROM_ABI constexpr vector(
- from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __base_type(__alloc) {
+ _LIBCPP_HIDE_FROM_ABI constexpr vector(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
+ : __base_type(__a) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
>From d1aedd0093ff97508547c852ff58bbc623c4a529 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 5 Feb 2026 21:58:27 +0000
Subject: [PATCH 22/39] works around a Clang 20 bug
---
libcxx/include/__vector/layout.h | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 1133bb1e79c99..d5e6c6042c5bf 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -123,15 +123,15 @@ class __vector_layout {
// Cannot be defaulted, since `_LIBCPP_COMPRESSED_PAIR` isn't an aggregate before C++14.
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __capacity_() {}
+ : __capacity_(__zero_boundary_type()) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __capacity_(), __alloc_(__a) {}
+ : __capacity_(__zero_boundary_type()), __alloc_(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __capacity_(), __alloc_(std::move(__a)) {}
+ : __capacity_(__zero_boundary_type()), __alloc_(std::move(__a)) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
@@ -140,8 +140,8 @@ class __vector_layout {
__capacity_(std::move(__other.__capacity_)),
__alloc_(std::move(__other.__alloc_)) {
__other.__begin_ = nullptr;
- __other.__boundary_ = __boundary_type();
- __other.__capacity_ = __boundary_type();
+ __other.__boundary_ = __zero_boundary_type();
+ __other.__capacity_ = __zero_boundary_type();
}
/// Returns a reference to the stored allocator.
@@ -222,11 +222,11 @@ class __vector_layout {
__capacity_ = __other.__capacity_;
__other.__begin_ = nullptr;
- __other.__boundary_ = __boundary_type();
- __other.__capacity_ = __boundary_type();
+ __other.__boundary_ = __zero_boundary_type();
+ __other.__capacity_ = __zero_boundary_type();
}
- // The following member functions must be implemented per vector layout.
+ // Methods below this line must be implemented per vector layout.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT;
@@ -238,6 +238,8 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __size) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __end) _NOEXCEPT;
+ // Works around a Clang 20 zero-initialization bug on user-defined pointer types.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type __zero_boundary_type() _NOEXCEPT;
private:
pointer __begin_ = nullptr;
@@ -312,6 +314,11 @@ template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(pointer __ptr) _NOEXCEPT {
__capacity_ = static_cast<size_type>(__ptr - __begin_);
}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
+ return 0;
+}
#else
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -376,6 +383,11 @@ template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(pointer __ptr) _NOEXCEPT {
__capacity_ = __ptr;
}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
+ return nullptr;
+}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
_LIBCPP_END_NAMESPACE_STD
>From fa86238bf969479c58f1781542782e5ca8fde5e7 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 5 Feb 2026 22:40:21 +0000
Subject: [PATCH 23/39] formats and removes pretty Unicode characters
---
libcxx/include/__vector/layout.h | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index d5e6c6042c5bf..a1187a3d2af34 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -58,9 +58,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// __begin_ = 0xE4FD0, __end_ = 0xE4FF0, __capacity_ = 0xE5000
/// 0xE4FD0 0xE4FF0 0xE5000
/// v v v
-/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
-/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
-/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
+/// +---------------+--------+--------+--------+--------+--------+--------+---------------------+
+/// | ????????????? | 3174 | 5656 | 648 | 489 | ------ | ------ | ??????????????????? |
+/// +---------------+--------+--------+--------+--------+--------+--------+---------------------+
/// ^ ^ ^
/// __begin_ __end_ __capacity_
///
@@ -79,9 +79,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// __begin_ = 0xE4FD0, __size_ = 4, __capacity_ = 6
/// 0xE4FD0
/// v
-/// ┌───────────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────────────────┐
-/// │ ????????????? │ 3174 │ 5656 │ 648 │ 489 │ ------ │ ------ │ ??????????????????? │
-/// └───────────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────────────────┘
+/// +---------------+--------+--------+--------+--------+--------+--------+---------------------+
+/// | ????????????? | 3174 | 5656 | 648 | 489 | ------ | ------ | ??????????????????? |
+/// +---------------+--------+--------+--------+--------+--------+--------+---------------------+
/// ^
/// __begin_
///
@@ -239,7 +239,8 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __size) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __end) _NOEXCEPT;
// Works around a Clang 20 zero-initialization bug on user-defined pointer types.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type __zero_boundary_type() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type
+ __zero_boundary_type() _NOEXCEPT;
private:
pointer __begin_ = nullptr;
@@ -316,7 +317,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type
+__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return 0;
}
#else
@@ -385,7 +387,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type
+__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return nullptr;
}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
>From c4cda39d6ee743f0e38d16421e5b7b616beaabb6 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Feb 2026 00:19:52 +0000
Subject: [PATCH 24/39] adds some non-const overloads
---
libcxx/include/__vector/layout.h | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index a1187a3d2af34..6412df1de8d00 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -159,7 +159,11 @@ class __vector_layout {
///
/// `__begin_ptr()` is not called `data()` because `vector::data()` returns `T*`, but `__begin_`
/// is allowed to be a fancy pointer.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __begin_ptr() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __begin_ptr() _NOEXCEPT {
+ return __begin_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __begin_ptr() const _NOEXCEPT {
return __begin_;
}
@@ -232,7 +236,8 @@ class __vector_layout {
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp& back() _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const& back() const _NOEXCEPT;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_ptr() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_ptr() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __end_ptr() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(size_type __size) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
@@ -285,6 +290,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() co
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__end_ptr() _NOEXCEPT {
+ return __begin_ + __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::const_pointer
__vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __begin_ + __boundary_;
}
@@ -351,6 +362,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() co
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__end_ptr() _NOEXCEPT {
+ return __boundary_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::const_pointer
__vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __boundary_;
}
>From af0f21f48cad3cea1a8a80b01bbd8e8e63b91e2e Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Feb 2026 00:20:08 +0000
Subject: [PATCH 25/39] [libcxx] tightens `__add_alignment_assumption` return
type
`__add_alignment_assumption` unilaterally returned a `pointer`, even
when passed a `const_pointer`. This was surfaced by some (but not all)
CI jobs when rebasing `std::vector` to have a layout type.
---
libcxx/include/__vector/vector.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 8546e7cc38d06..005f31e085bc4 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -821,16 +821,16 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
template <class _Ptr = pointer, __enable_if_t<is_pointer<_Ptr>::value, int> = 0>
- static _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI pointer
+ static _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Ptr
__add_alignment_assumption(_Ptr __p) _NOEXCEPT {
if (!__libcpp_is_constant_evaluated()) {
- return static_cast<pointer>(__builtin_assume_aligned(__p, _LIBCPP_ALIGNOF(decltype(*__p))));
+ return static_cast<_Ptr>(__builtin_assume_aligned(__p, _LIBCPP_ALIGNOF(decltype(*__p))));
}
return __p;
}
template <class _Ptr = pointer, __enable_if_t<!is_pointer<_Ptr>::value, int> = 0>
- static _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI pointer
+ static _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Ptr
__add_alignment_assumption(_Ptr __p) _NOEXCEPT {
return __p;
}
>From b511b626ed7b6f3802c51278d0cfdb7b7e8e1d10 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Feb 2026 02:34:14 +0000
Subject: [PATCH 26/39] adds missing __capacity_ptr
---
libcxx/include/__vector/layout.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 6412df1de8d00..7614184e72373 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -238,6 +238,8 @@ class __vector_layout {
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const& back() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_ptr() _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __end_ptr() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_ptr() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __capacity_ptr() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(size_type __size) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
@@ -300,6 +302,18 @@ __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __begin_ + __boundary_;
}
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__capacity_ptr() _NOEXCEPT {
+ return __begin_ + __capacity_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::const_pointer
+__vector_layout<_Tp, _Alloc>::__capacity_ptr() const _NOEXCEPT {
+ return __begin_ + __capacity_;
+}
+
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__invariants() const _NOEXCEPT {
if (__begin_ == nullptr)
@@ -372,6 +386,18 @@ __vector_layout<_Tp, _Alloc>::__end_ptr() const _NOEXCEPT {
return __boundary_;
}
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::pointer
+__vector_layout<_Tp, _Alloc>::__capacity_ptr() _NOEXCEPT {
+ return __capacity_;
+}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::const_pointer
+__vector_layout<_Tp, _Alloc>::__capacity_ptr() const _NOEXCEPT {
+ return __capacity_;
+}
+
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__invariants() const _NOEXCEPT {
if (__begin_ == nullptr)
>From 31eada3f6332bd3b2cd5d02ea967c28e552d808e Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Feb 2026 23:24:00 +0000
Subject: [PATCH 27/39] adjusts documentation
---
libcxx/include/__vector/layout.h | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 7614184e72373..5082aec23fd7f 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -43,16 +43,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// **Pointer-based layout**
///
/// The pointer-based layout uses two more pointers in addition to `__begin_`. The second pointer
-/// (called `__end_`) past the end of the part of the buffer that holds valid elements. The pointer
-/// (called `__capacity_`) points past the end of the allocated buffer. This is the default
-/// representation for libc++ due to historical reasons.
+/// (called `__end_`) points past the end of the part of the buffer that holds valid elements.
+/// Another pointer (called `__capacity_`) points past the end of the allocated buffer. This is the
+/// default representation for libc++ due to historical reasons.
///
-/// The second pointer has three primary use-cases:
+/// The `__end_` pointer has three primary use-cases:
/// * to compute the size of the vector; and
/// * to construct the past-the-end iterator; and
/// * to indicate where the next element should be appended.
///
-/// The third pointer is used to compute the capacity of the vector, which lets the vector know how
+/// The `__capacity_` is used to compute the capacity of the vector, which lets the vector know how
/// many elements can be added to the vector before a reallocation is necessary.
///
/// __begin_ = 0xE4FD0, __end_ = 0xE4FF0, __capacity_ = 0xE5000
@@ -65,16 +65,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// __begin_ __end_ __capacity_
///
/// Figure 1: A visual representation of a pointer-based `std::vector<short>`. This vector has
-/// four elements, with the capacity to store six.
+/// four elements, with the capacity to store six. Boxes with numbers are valid elements within
+/// the vector, and boxes with `xx` have been allocated, but aren't being used as elements right
+/// now.
///
/// This is the default layout for libc++.
///
/// **Size-based layout**
///
/// The size-based layout uses integers to track its size and capacity, and computes pointers to
-/// past-the-end of the valid range and the whole buffer only when it's necessary. This layout is
-/// opt-in, but yields a significant performance boost relative to the pointer-based layout (see
-/// below).
+/// past-the-end of the valid range and the whole buffer only when it's necessary. Programs using
+/// the size-based layout have been measured to yield improved compute and memory performance over
+/// the pointer-based layout. Despite these promising measurements, the size-based layout is opt-in,
+/// to preserve ABI compatibility with prebuilt binaries. Given the improved performance, we
+/// recommend preferring the size-based layout in the absence of such ABI constraints.
///
/// __begin_ = 0xE4FD0, __size_ = 4, __capacity_ = 6
/// 0xE4FD0
@@ -85,9 +89,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// ^
/// __begin_
///
-/// Figure 2: A visual representation of this a pointer-based layout. Blank boxes are not a part
-/// of the vector's allocated buffer. Boxes with numbers are valid elements within the vector,
-/// and boxes with `xx` have been allocated, but aren't being used as elements right now.
+/// Figure 2: A visual representation of this a size-based layout. Blank boxes are not a part
+/// of the vector's allocated buffer.
//
/// We conducted an extensive A/B test on production software to confirm that the size-based layout
/// improves compute performance by 0.5%, and decreases system memory usage by up to 0.33%.
@@ -149,7 +152,6 @@ class __vector_layout {
return __alloc_;
}
- /// Returns a reference to the stored allocator.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
__alloc() const _NOEXCEPT {
return __alloc_;
>From 77322844a76ed456ce92a0c0cbc82bb9b0612f6b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Feb 2026 23:24:35 +0000
Subject: [PATCH 28/39] reverts default constructor
---
libcxx/include/__vector/vector.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 005f31e085bc4..ef025edb6767a 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -146,7 +146,8 @@ class vector : __vector_layout<_Tp, _Allocator> {
//
// [vector.cons], construct/copy/destroy
//
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector() = default;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector()
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a)
#if _LIBCPP_STD_VER <= 14
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
>From 7611be6d3826969c3ad2dd73c1395babd1f441b4 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 10 Feb 2026 18:41:27 +0000
Subject: [PATCH 29/39] changes from inheritance to compositon
See https://github.com/llvm/llvm-project/pull/155330/changes#r2774234713.
---
libcxx/include/__vector/layout.h | 2 +-
libcxx/include/__vector/vector.h | 329 ++++++++++++++--------------
libcxx/utils/gdb/libcxx/printers.py | 19 +-
3 files changed, 169 insertions(+), 181 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 5082aec23fd7f..0442f0727d1a6 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -222,7 +222,7 @@ class __vector_layout {
__other.__swap_layouts(__begin_, __boundary_, __capacity_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_layout(__vector_layout& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_without_allocator(__vector_layout& __other) _NOEXCEPT {
__begin_ = __other.__begin_;
__boundary_ = __other.__boundary_;
__capacity_ = __other.__capacity_;
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index ef025edb6767a..bdf8be1f85252 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -86,24 +86,11 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector : __vector_layout<_Tp, _Allocator> {
+class vector {
using __base_type _LIBCPP_NODEBUG = __vector_layout<_Tp, _Allocator>;
using __boundary_type _LIBCPP_NODEBUG = typename __base_type::__boundary_type;
using _SplitBuffer _LIBCPP_NODEBUG = typename __base_type::_SplitBuffer;
- using __base_type::__alloc;
- using __base_type::__begin_ptr;
- using __base_type::__boundary_representation;
- using __base_type::__capacity_representation;
- using __base_type::__end_ptr;
- using __base_type::__is_full;
- using __base_type::__move_layout;
- using __base_type::__remaining_capacity;
- using __base_type::__set_boundary;
- using __base_type::__set_capacity;
- using __base_type::__set_valid_range;
- using __base_type::__swap_layouts;
-
public:
//
// Types
@@ -154,7 +141,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
#else
noexcept
#endif
- : __base_type(__a) {
+ : __layout_(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -168,7 +155,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __base_type(__a) {
+ : __layout_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -190,7 +177,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __base_type(__a) {
+ : __layout_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -213,7 +200,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __base_type(__a) {
+ : __layout_(__a) {
__init_with_sentinel(__first, __last);
}
@@ -234,7 +221,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __base_type(__a) {
+ : __layout_(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -242,7 +229,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
#if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
- : __base_type(__a) {
+ : __layout_(__a) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -259,10 +246,10 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__begin_ptr() != nullptr) {
+ if (__vec_.__layout_.__begin_ptr() != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_ptr(), __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__layout_.__alloc(), __vec_.__layout_.__begin_ptr(), __vec_.capacity());
}
}
@@ -274,13 +261,13 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __base_type(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) {
- __init_with_size(__x.__begin_ptr(), __x.__end_ptr(), __x.size());
+ : __layout_(__alloc_traits::select_on_container_copy_construction(__x.__layout_.__alloc())) {
+ __init_with_size(__x.__layout_.__begin_ptr(), __x.__layout_.__end_ptr(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __base_type(__a) {
- __init_with_size(__x.__begin_ptr(), __x.__end_ptr(), __x.size());
+ : __layout_(__a) {
+ __init_with_size(__x.__layout_.__begin_ptr(), __x.__layout_.__end_ptr(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -291,7 +278,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __base_type(__a) {
+ : __layout_(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -354,23 +341,23 @@ class vector : __vector_layout<_Tp, _Allocator> {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return this->__alloc();
+ return this->__layout_.__alloc();
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_ptr()));
+ return __make_iter(__add_alignment_assumption(this->__layout_.__begin_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_ptr()));
+ return __make_iter(__add_alignment_assumption(this->__layout_.__begin_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__end_ptr()));
+ return __make_iter(__add_alignment_assumption(__layout_.__end_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__end_ptr()));
+ return __make_iter(__add_alignment_assumption(__layout_.__end_ptr()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
@@ -405,17 +392,17 @@ class vector : __vector_layout<_Tp, _Allocator> {
// [vector.capacity], capacity
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __base_type::size();
+ return __layout_.size();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __base_type::capacity();
+ return __layout_.capacity();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __base_type::empty();
+ return __layout_.empty();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(__alloc()), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__layout_.__alloc()), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -425,50 +412,50 @@ class vector : __vector_layout<_Tp, _Allocator> {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_ptr()[__n];
+ return this->__layout_.__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_ptr()[__n];
+ return this->__layout_.__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_ptr()[__n];
+ return this->__layout_.__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_ptr()[__n];
+ return this->__layout_.__begin_ptr()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_ptr();
+ return *this->__layout_.__begin_ptr();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_ptr();
+ return *this->__layout_.__begin_ptr();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __base_type::back();
+ return __layout_.back();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __base_type::back();
+ return __layout_.back();
}
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(this->__begin_ptr());
+ return std::__to_address(this->__layout_.__begin_ptr());
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(this->__begin_ptr());
+ return std::__to_address(this->__layout_.__begin_ptr());
}
//
@@ -491,7 +478,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -500,15 +487,15 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __len = ranges::distance(__range);
- if (__len < static_cast<difference_type>(__remaining_capacity())) {
+ if (__len < static_cast<difference_type>(__layout_.__remaining_capacity())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- _SplitBuffer __buffer(__recommend(size() + __len), size(), __alloc());
+ _SplitBuffer __buffer(__recommend(size() + __len), size(), __layout_.__alloc());
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
} else {
- vector __buffer(__alloc());
+ vector __buffer(__layout_.__alloc());
for (auto&& __val : __range)
__buffer.emplace_back(std::forward<decltype(__val)>(__val));
append_range(ranges::as_rvalue_view(__buffer));
@@ -518,7 +505,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
- this->__destruct_at_end(__end_ptr() - 1);
+ this->__destruct_at_end(__layout_.__end_ptr() - 1);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x);
@@ -574,7 +561,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(this->__begin_ptr());
+ __base_destruct_at_end(this->__layout_.__begin_ptr());
__annotate_shrink(__old_size);
}
@@ -588,9 +575,13 @@ class vector : __vector_layout<_Tp, _Allocator> {
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
#endif
- using __base_type::__invariants;
+ bool __invariants() {
+ return __layout_.__invariants();
+ }
private:
+ __base_type __layout_;
+
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
@@ -603,9 +594,9 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(this->__alloc(), __n);
- __set_valid_range(__allocation.ptr, static_cast<size_type>(0));
- __set_capacity(__allocation.count);
+ auto __allocation = std::__allocate_at_least(this->__layout_.__alloc(), __n);
+ __layout_.__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
+ __layout_.__set_capacity(__allocation.count);
__annotate_new(0);
}
@@ -654,7 +645,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc(), *__first);
+ __temp_value<value_type, _Allocator> __tmp(this->__layout_.__alloc(), *__first);
*__position = std::move(__tmp.get());
}
}
@@ -692,7 +683,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(this->__begin_ptr()),
+ std::__wrap_iter<pointer>(this->__layout_.__begin_ptr()),
std::__wrap_iter<pointer>(this->__capacity_ptr()));
#else
return iterator(__p);
@@ -704,7 +695,7 @@ class vector : __vector_layout<_Tp, _Allocator> {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(this->__begin_ptr()),
+ std::__wrap_iter<const_pointer>(this->__layout_.__begin_ptr()),
std::__wrap_iter<const_pointer>(this->__capacity_ptr()));
#else
return const_iterator(__p);
@@ -761,14 +752,14 @@ class vector : __vector_layout<_Tp, _Allocator> {
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
- : __v_(__v), __pos_(__v.__end_ptr()), __new_end_(__pos_ + __n) {
+ : __v_(__v), __pos_(__v.__layout_.__end_ptr()), __new_end_(__pos_ + __n) {
__v_.__annotate_increase(__n);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __v_.__set_boundary(__pos_);
+ __v_.__layout_.__set_boundary(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__begin_ptr());
+ __v_.__annotate_shrink(__new_end_ - __v_.__layout_.__begin_ptr());
}
}
@@ -781,10 +772,10 @@ class vector : __vector_layout<_Tp, _Allocator> {
};
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
- pointer __soon_to_be_end = __end_ptr();
+ pointer __soon_to_be_end = __layout_.__end_ptr();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(this->__alloc(), std::__to_address(--__soon_to_be_end));
- __set_boundary(__new_last);
+ __alloc_traits::destroy(this->__layout_.__alloc(), std::__to_address(--__soon_to_be_end));
+ __layout_.__set_boundary(__new_last);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {
@@ -802,21 +793,21 @@ class vector : __vector_layout<_Tp, _Allocator> {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (this->__alloc() != __c.__alloc()) {
+ if (this->__layout_.__alloc() != __c.__layout_.__alloc()) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc(), this->__begin_ptr(), capacity());
- __set_valid_range(nullptr, static_cast<size_type>(0));
- __set_capacity(static_cast<__boundary_type>(0));
+ __alloc_traits::deallocate(this->__layout_.__alloc(), this->__layout_.__begin_ptr(), capacity());
+ __layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __layout_.__set_capacity(static_cast<__boundary_type>(0));
}
- this->__alloc() = __c.__alloc();
+ this->__layout_.__alloc() = __c.__layout_.__alloc();
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- this->__alloc() = std::move(__c.__alloc());
+ this->__layout_.__alloc() = std::move(__c.__layout_.__alloc());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -858,7 +849,7 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__begin_ptr(), size()) into the front of __v and swaps the
+// __swap_out_circular_buffer relocates the objects in [__layout_.__begin_ptr(), size()) into the front of __v and swaps the
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
@@ -866,45 +857,45 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc(),
- std::__to_address(__begin_ptr()),
- std::__to_address(__end_ptr()),
+ this->__layout_.__alloc(),
+ std::__to_address(__layout_.__begin_ptr()),
+ std::__to_address(__layout_.__end_ptr()),
std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
- __set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __layout_.__set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
- __swap_layouts(__v);
+ __layout_.__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__begin_ptr(), __p) into the front of __v, the objects in
+// __swap_out_circular_buffer relocates the objects in [__layout_.__begin_ptr(), __p) into the front of __v, the objects in
// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __begin_ptr()) objects in the front and space for at least (size() - __p) objects in the back. This
-// function has a strong exception guarantee if __begin_ptr() == __p || size() == __p.
+// exactly (__p - __layout_.__begin_ptr()) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __layout_.__begin_ptr() == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v, pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
- pointer __end = __end_ptr();
- // Relocate [__p, __end) first to avoid having a hole in [__begin_ptr(), __end)
- // in case something in [__begin_ptr(), __p) throws.
+ pointer __end = __layout_.__end_ptr();
+ // Relocate [__p, __end) first to avoid having a hole in [__layout_.__begin_ptr(), __end)
+ // in case something in [__layout_.__begin_ptr(), __p) throws.
std::__uninitialized_allocator_relocate(
- this->__alloc(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ this->__layout_.__alloc(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
- __set_boundary(__boundary_representation() -
+ __layout_.__set_boundary(__layout_.__boundary_representation() -
__relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __begin_ptr());
+ auto __new_begin = __v.begin() - (__p - __layout_.__begin_ptr());
std::__uninitialized_allocator_relocate(
- this->__alloc(), std::__to_address(__begin_ptr()), std::__to_address(__p), std::__to_address(__new_begin));
+ this->__layout_.__alloc(), std::__to_address(__layout_.__begin_ptr()), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
- __set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __layout_.__set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
- __swap_layouts(__v);
+ __layout_.__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
return __ret;
@@ -912,12 +903,12 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v, pointer _
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (this->__begin_ptr() != nullptr) {
+ if (this->__layout_.__begin_ptr() != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc(), this->__begin_ptr(), capacity());
- __set_valid_range(nullptr, static_cast<size_type>(0));
- __set_capacity(static_cast<size_type>(0));
+ __alloc_traits::deallocate(this->__layout_.__alloc(), this->__layout_.__begin_ptr(), capacity());
+ __layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __layout_.__set_capacity(static_cast<size_type>(0));
}
}
@@ -934,7 +925,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
return std::max<size_type>(2 * __cap, __new_size);
}
-// Default constructs __n objects starting at __end_ptr()
+// Default constructs __n objects starting at __layout_.__end_ptr()
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -944,11 +935,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_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->__alloc(), std::__to_address(__pos));
+ __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos));
}
}
-// Copy constructs __n objects starting at __end_ptr() from __x
+// Copy constructs __n objects starting at __layout_.__end_ptr() from __x
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -960,7 +951,7 @@ 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->__alloc(), std::__to_address(__pos), __x);
+ __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), __x);
}
}
@@ -970,7 +961,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
__tx.__pos_ =
- std::__uninitialized_allocator_copy(this->__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
+ std::__uninitialized_allocator_copy(this->__layout_.__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -980,19 +971,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __base_type(std::move(__x.__alloc())) {
- __set_valid_range(__x.__begin_ptr(), __x.__boundary_representation());
- __set_capacity(__x.__capacity_representation());
- __x.__set_valid_range(nullptr, static_cast<size_type>(0));
- __x.__set_capacity(static_cast<size_type>(0));
+ : __layout_(std::move(__x.__layout_.__alloc())) {
+ __layout_.__set_valid_range(__x.__layout_.__begin_ptr(), __x.__layout_.__boundary_representation());
+ __layout_.__set_capacity(__x.__layout_.__capacity_representation());
+ __x.__layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __x.__layout_.__set_capacity(static_cast<size_type>(0));
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __base_type(__a) {
- if (__a == __x.__alloc()) {
- __move_layout(static_cast<__base_type&>(__x));
+ : __layout_(__a) {
+ if (__a == __x.__layout_.__alloc()) {
+ __layout_.__move_without_allocator(__x.__layout_);
} else {
typedef move_iterator<iterator> _Ip;
__init_with_size(_Ip(__x.begin()), _Ip(__x.end()), __x.size());
@@ -1002,7 +993,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (this->__alloc() != __c.__alloc()) {
+ if (this->__layout_.__alloc() != __c.__layout_.__alloc()) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1014,7 +1005,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- __move_layout(static_cast<__base_type&>(__c));
+ __layout_.__move_without_allocator(__c.__layout_);
}
template <class _Tp, class _Allocator>
@@ -1022,7 +1013,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__begin_ptr(), __x.__end_ptr());
+ assign(__x.__layout_.__begin_ptr(), __x.__layout_.__end_ptr());
}
return *this;
}
@@ -1031,8 +1022,8 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __begin_ptr();
- pointer __end = __end_ptr();
+ pointer __cur = __layout_.__begin_ptr();
+ pointer __end = __layout_.__end_ptr();
for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
if (__cur != __end) {
@@ -1051,10 +1042,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
auto const __size = size();
if (__new_size > __size) {
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_ptr()).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__layout_.__begin_ptr()).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, this->__begin_ptr()).second;
+ pointer __m = std::__copy(std::move(__first), __last, this->__layout_.__begin_ptr()).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1068,11 +1059,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(this->__begin_ptr(), std::min(__n, __s), __u);
+ std::fill_n(this->__layout_.__begin_ptr(), std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(this->__begin_ptr() + __n);
+ this->__destruct_at_end(this->__layout_.__begin_ptr() + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1085,7 +1076,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- _SplitBuffer __v(__n, size(), this->__alloc());
+ _SplitBuffer __v(__n, size(), this->__layout_.__alloc());
__swap_out_circular_buffer(__v);
}
}
@@ -1096,7 +1087,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- _SplitBuffer __v(size(), size(), this->__alloc());
+ _SplitBuffer __v(size(), size(), this->__layout_.__alloc());
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1113,13 +1104,13 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__boundary_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- _SplitBuffer __v(__recommend(size() + 1), size(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), size(), this->__layout_.__alloc());
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(this->__alloc(), std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
- return __boundary_representation();
+ return __layout_.__boundary_representation();
}
// This makes the compiler inline `__else()` if `__cond` is known to be false. Currently LLVM doesn't do that without
@@ -1149,16 +1140,16 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
- auto __current_boundary = __boundary_representation();
+ auto __current_boundary = __layout_.__boundary_representation();
std::__if_likely_else(
- __current_boundary < __capacity_representation(),
+ __current_boundary < __layout_.__capacity_representation(),
[&] {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
++__current_boundary;
},
[&] { __current_boundary = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
- __set_boundary(__current_boundary);
+ __layout_.__set_boundary(__current_boundary);
#if _LIBCPP_STD_VER >= 17
return back();
#endif
@@ -1170,8 +1161,8 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = this->__begin_ptr() + __ps;
- this->__destruct_at_end(std::move(__p + 1, __end_ptr(), __p));
+ pointer __p = this->__layout_.__begin_ptr() + __ps;
+ this->__destruct_at_end(std::move(__p + 1, __layout_.__end_ptr(), __p));
return __make_iter(__p);
}
@@ -1179,9 +1170,9 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = this->__begin_ptr() + (__first - begin());
+ pointer __p = this->__layout_.__begin_ptr() + (__first - begin());
if (__first != __last) {
- this->__destruct_at_end(std::move(__p + (__last - __first), __end_ptr(), __p));
+ this->__destruct_at_end(std::move(__p + (__last - __first), __layout_.__end_ptr(), __p));
}
return __make_iter(__p);
}
@@ -1189,13 +1180,13 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
- pointer __old_last = __end_ptr();
+ pointer __old_last = __layout_.__end_ptr();
difference_type __n = __old_last - __to;
{
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->__alloc(), std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1204,9 +1195,9 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = this->__begin_ptr() + (__position - begin());
- if (!__is_full()) {
- pointer __end = __end_ptr();
+ pointer __p = this->__layout_.__begin_ptr() + (__position - begin());
+ if (!__layout_.__is_full()) {
+ pointer __end = __layout_.__end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(__x);
} else {
@@ -1217,7 +1208,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1227,9 +1218,9 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = this->__begin_ptr() + (__position - begin());
- if (!__is_full()) {
- pointer __end = __end_ptr();
+ pointer __p = this->__layout_.__begin_ptr() + (__position - begin());
+ if (!__layout_.__is_full()) {
+ pointer __end = __layout_.__end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(std::move(__x));
} else {
@@ -1237,7 +1228,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1248,18 +1239,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = this->__begin_ptr() + (__position - begin());
- if (!__is_full()) {
- pointer __end = __end_ptr();
+ pointer __p = this->__layout_.__begin_ptr() + (__position - begin());
+ if (!__layout_.__is_full()) {
+ pointer __end = __layout_.__end_ptr();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc(), std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(this->__layout_.__alloc(), std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- _SplitBuffer __v(__recommend(size() + 1), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1269,11 +1260,11 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = this->__begin_ptr() + (__position - begin());
+ pointer __p = this->__layout_.__begin_ptr() + (__position - begin());
if (__n > 0) {
- if (__n <= __remaining_capacity()) {
+ if (__n <= __layout_.__remaining_capacity()) {
size_type __old_n = __n;
- pointer __end = __end_ptr();
+ pointer __end = __layout_.__end_ptr();
pointer __old_last = __end;
if (__n > static_cast<size_type>(__end - __p)) {
size_type __cx = __n - (__end - __p);
@@ -1288,7 +1279,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- _SplitBuffer __v(__recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + __n), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1301,29 +1292,29 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = this->__begin_ptr() + __off;
- pointer __old_last = __end_ptr();
- for (; !__is_full() && __first != __last; ++__first)
+ pointer __p = this->__layout_.__begin_ptr() + __off;
+ pointer __old_last = __layout_.__end_ptr();
+ for (; !__layout_.__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
if (__first == __last)
- (void)std::rotate(__p, __old_last, __end_ptr());
+ (void)std::rotate(__p, __old_last, __layout_.__end_ptr());
else {
- _SplitBuffer __v(__alloc());
- pointer __end = __end_ptr();
+ _SplitBuffer __v(__layout_.__alloc());
+ pointer __end = __layout_.__end_ptr();
auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc(), __old_last, __end));
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__layout_.__alloc(), __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
_SplitBuffer __merged(
- __recommend(size() + __v.size()), __off, __alloc()); // has `__off` positions available at the front
+ __recommend(size() + __v.size()), __off, __layout_.__alloc()); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc(), std::__to_address(__old_last), std::__to_address(__end_ptr()), std::__to_address(__merged.end()));
- __guard.__complete(); // Release the guard once objects in [__old_last_, __end_ptr()) have been successfully
+ __layout_.__alloc(), std::__to_address(__old_last), std::__to_address(__layout_.__end_ptr()), std::__to_address(__merged.end()));
+ __guard.__complete(); // Release the guard once objects in [__old_last_, __layout_.__end_ptr()) have been successfully
// relocated.
- __merged.__set_sentinel(__merged.end() + (__end_ptr() - __old_last));
- __set_boundary(__old_last);
+ __merged.__set_sentinel(__merged.end() + (__layout_.__end_ptr() - __old_last));
+ __layout_.__set_boundary(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc(), std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __layout_.__alloc(), std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1336,10 +1327,10 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = this->__begin_ptr() + (__position - begin());
+ pointer __p = this->__layout_.__begin_ptr() + (__position - begin());
if (__n > 0) {
- if (__n <= static_cast<difference_type>(__remaining_capacity())) {
- pointer __end = __end_ptr();
+ if (__n <= static_cast<difference_type>(__layout_.__remaining_capacity())) {
+ pointer __end = __layout_.__end_ptr();
pointer __old_last = __end;
difference_type __dx = __end - __p;
if (__n > __dx) {
@@ -1362,7 +1353,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- _SplitBuffer __v(__recommend(size() + __n), __p - this->__begin_ptr(), this->__alloc());
+ _SplitBuffer __v(__recommend(size() + __n), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1377,12 +1368,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc());
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __layout_.__alloc());
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ptr() + __new_size);
+ this->__destruct_at_end(this->__layout_.__begin_ptr() + __new_size);
}
}
@@ -1393,12 +1384,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- _SplitBuffer __v(__recommend(__new_size), __current_size, __alloc());
+ _SplitBuffer __v(__recommend(__new_size), __current_size, __layout_.__alloc());
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ptr() + __new_size);
+ this->__destruct_at_end(this->__layout_.__begin_ptr() + __new_size);
}
}
@@ -1411,10 +1402,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
#endif
{
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc() == __x.__alloc(),
+ __alloc_traits::propagate_on_container_swap::value || __layout_.__alloc() == __x.__layout_.__alloc(),
"vector::swap: Either propagate_on_container_swap must be true"
" or the allocators must compare equal");
- __base_type::swap(static_cast<__base_type&>(__x));
+ __layout_.swap(__x.__layout_);
}
#if _LIBCPP_STD_VER >= 20
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index e03c9ba9a7dc2..51867dea99438 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -359,18 +359,15 @@ def __init__(self, val):
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- for i in self.val.type.fields():
- if i.is_base_class:
- base = val[i]
- break
-
- begin = base["__begin_"]
- if self.val.type.fields()[0].is_base_class:
- boundary = base["__boundary_"]
- capacity = base["__capacity_"]
+ layout = self.val["__layout_"]
+ if layout:
+ begin = layout["__begin_"]
+ boundary = layout["__boundary_"]
+ capacity = layout["__capacity_"]
else:
- boundary = base["__end_"]
- capacity = base["__cap_"]
+ begin = self.val["__begin_"]
+ boundary = self.val["__end_"]
+ capacity = self.val["__cap_"]
# We test for integers because `vector<T>::size_type` is required to
# be an unsigned integer, whereas `vector<T>::pointer` can be any
>From e1e0067394309dc2de14b906bf895733c65b556e Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 10 Feb 2026 19:22:43 +0000
Subject: [PATCH 30/39] adds assertions
---
libcxx/include/__vector/vector.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index bdf8be1f85252..5e10c328889ab 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -592,6 +592,11 @@ class vector {
// Postcondition: capacity() >= __n
// Postcondition: size() == 0
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
+ _LIBCPP_ASSERT_INTERNAL(__layout_.begin() == nullptr, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's begin pointer.");
+ _LIBCPP_ASSERT_INTERNAL(__layout_.empty(), "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's size.");
+ _LIBCPP_ASSERT_INTERNAL(capacity() == 0, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's capacity.");
+ _LIBCPP_ASSERT_INTERNAL(__n > 0, "vector::__vallocate cannot allocate 0 bytes");
+
if (__n > max_size())
this->__throw_length_error();
auto __allocation = std::__allocate_at_least(this->__layout_.__alloc(), __n);
>From ff7e0948f4aff89fd8aab0d748bd38b0ec0c81a2 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 10 Feb 2026 19:23:51 +0000
Subject: [PATCH 31/39] uglifies __vector_layout members
---
libcxx/include/__vector/layout.h | 30 +++++++++++++++---------------
libcxx/include/__vector/vector.h | 10 +++++-----
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 0442f0727d1a6..b705b696e263e 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -233,11 +233,11 @@ class __vector_layout {
}
// Methods below this line must be implemented per vector layout.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp& back() _NOEXCEPT;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const& back() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __size() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __capacity() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __empty() const _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp& __back() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const& __back() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_ptr() _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __end_ptr() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_ptr() _NOEXCEPT;
@@ -267,28 +267,28 @@ class __vector_layout {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT {
+typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::__size() const _NOEXCEPT {
return __boundary_;
}
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::size_type
-__vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT {
+__vector_layout<_Tp, _Alloc>::__capacity() const _NOEXCEPT {
return __capacity_;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__empty() const _NOEXCEPT {
return __boundary_ == 0;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::__back() _NOEXCEPT {
return __begin_[__boundary_ - 1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::__back() const _NOEXCEPT {
return __begin_[__boundary_ - 1];
}
@@ -351,28 +351,28 @@ __vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
#else
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::size() const _NOEXCEPT {
+typename __vector_layout<_Tp, _Alloc>::size_type __vector_layout<_Tp, _Alloc>::__size() const _NOEXCEPT {
return static_cast<size_type>(__boundary_ - __begin_);
}
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::size_type
-__vector_layout<_Tp, _Alloc>::capacity() const _NOEXCEPT {
+__vector_layout<_Tp, _Alloc>::__capacity() const _NOEXCEPT {
return static_cast<size_type>(__capacity_ - __begin_);
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::empty() const _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __vector_layout<_Tp, _Alloc>::__empty() const _NOEXCEPT {
return __begin_ == __boundary_;
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::back() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __vector_layout<_Tp, _Alloc>::__back() _NOEXCEPT {
return __boundary_[-1];
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::back() const _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp const& __vector_layout<_Tp, _Alloc>::__back() const _NOEXCEPT {
return __boundary_[-1];
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 5e10c328889ab..968bf71be8ade 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -392,13 +392,13 @@ class vector {
// [vector.capacity], capacity
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __layout_.size();
+ return __layout_.__size();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __layout_.capacity();
+ return __layout_.__capacity();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __layout_.empty();
+ return __layout_.__empty();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
@@ -440,11 +440,11 @@ class vector {
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __layout_.back();
+ return __layout_.__back();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __layout_.back();
+ return __layout_.__back();
}
//
>From d52a634909a2b4e003196aca9485bc181f5bca6a Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 10 Feb 2026 20:53:49 +0000
Subject: [PATCH 32/39] renames parameters to improve readability
---
libcxx/include/__vector/layout.h | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index b705b696e263e..09b1060964471 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -201,14 +201,14 @@ class __vector_layout {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __set_boundary(__size);
+ __set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
+ __begin_ = __new_begin;
+ __set_boundary(__new_size);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __set_boundary(__end);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
+ __begin_ = __new_begin;
+ __set_boundary(__new_end);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __other) _NOEXCEPT {
@@ -243,10 +243,10 @@ class __vector_layout {
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_ptr() _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __capacity_ptr() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(size_type __size) _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __end) _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __size) _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __end) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(size_type __n) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __ptr) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __n) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __ptr) _NOEXCEPT;
// Works around a Clang 20 zero-initialization bug on user-defined pointer types.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type
__zero_boundary_type() _NOEXCEPT;
>From 7aa62a60020a98009728e94c12b8d4d29fbcca21 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 10 Feb 2026 20:55:23 +0000
Subject: [PATCH 33/39] adds `__zero_relative_to_begin` and reset methods to
`__vector_layout`
Using `static_cast<size_type>(0)` was a fairly subtle way to avoid
overload resolution ambiguity between `size_type{0}` and `nullptr`.
This commit intends to improve readability by replacing that cast
with a named function to communicate intent.
This commit introduces a method that resets `__begin_`, `__boundary_`,
and `__capacity_` together. Since the capacity is only ever zeroed out
when `__begin_` and `__boundary_` are also zeroed out, so these should
be executed by a single function call.
---
libcxx/include/__vector/layout.h | 30 +++++++++++++++++++++++++++---
libcxx/include/__vector/vector.h | 21 +++++++++++++--------
2 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 09b1060964471..98eccdaa9c8b8 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -211,6 +211,13 @@ class __vector_layout {
__set_boundary(__new_end);
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset_without_allocator() _NOEXCEPT
+ {
+ __begin_ = nullptr;
+ __set_boundary(__zero_relative_to_begin());
+ __set_capacity(__zero_relative_to_begin());
+ }
+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __other) _NOEXCEPT {
std::swap(__begin_, __other.__begin_);
std::swap(__boundary_, __other.__boundary_);
@@ -227,9 +234,7 @@ class __vector_layout {
__boundary_ = __other.__boundary_;
__capacity_ = __other.__capacity_;
- __other.__begin_ = nullptr;
- __other.__boundary_ = __zero_boundary_type();
- __other.__capacity_ = __zero_boundary_type();
+ __other.__reset_without_allocator();
}
// Methods below this line must be implemented per vector layout.
@@ -247,6 +252,15 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __ptr) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __n) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __ptr) _NOEXCEPT;
+ /// Returns `__begin_` if `__boundary_type` is `pointer`, and `0` if it is `size_type`.
+ ///
+ /// Since `0` is implicitly convertible to both `size_type` and `nullptr`, `__set_boundary(0)` is
+ /// ambiguous. Using a named function optimises for the reader much more nicely than using an
+ /// explicit cast to `size_type`. In addition to describing intent, this function avoids extra
+ /// pointer arithmetic in the pointer-based `__set_boundary(size_type{})`.
+ ///
+ /// Note that this function cannot be used when setting `__begin_`.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __boundary_type __zero_relative_to_begin() _NOEXCEPT;
// Works around a Clang 20 zero-initialization bug on user-defined pointer types.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type
__zero_boundary_type() _NOEXCEPT;
@@ -343,6 +357,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
__capacity_ = static_cast<size_type>(__ptr - __begin_);
}
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
+ return 0;
+}
+
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
@@ -431,6 +450,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
__capacity_ = __ptr;
}
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
+ return __begin_;
+}
+
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp, _Alloc>::__boundary_type
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 968bf71be8ade..796d09eec4075 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -600,6 +600,14 @@ class vector {
if (__n > max_size())
this->__throw_length_error();
auto __allocation = std::__allocate_at_least(this->__layout_.__alloc(), __n);
+ // Since the pointer-based `__layout_.__zero_relative_to_begin()` returns a pointer to the
+ // memory that it currently holds, we can't use it when changing `__layout_.__begin_`. As such,
+ // we need to tell the layout that we want our layout to point to `__allocation.ptr`, and for it
+ // to be empty.
+ //
+ // We explicitly convert `0` to `size_type` to prevent ambiguity between `__vector_layout's`
+ // pointer-based and size-based `__set_valid_range` overloads, as `0` is implicitly convertible
+ // to `size_type`.
__layout_.__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__layout_.__set_capacity(__allocation.count);
__annotate_new(0);
@@ -802,8 +810,7 @@ class vector {
clear();
__annotate_delete();
__alloc_traits::deallocate(this->__layout_.__alloc(), this->__layout_.__begin_ptr(), capacity());
- __layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
- __layout_.__set_capacity(static_cast<__boundary_type>(0));
+ __layout_.__reset_without_allocator();
}
this->__layout_.__alloc() = __c.__layout_.__alloc();
}
@@ -867,7 +874,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
std::__to_address(__layout_.__end_ptr()),
std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
- __layout_.__set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __layout_.__set_boundary(__layout_.__zero_relative_to_begin()); // All the objects have been destroyed by relocating them.
__layout_.__swap_layouts(__v);
__v.__set_data(__v.begin());
@@ -898,7 +905,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v, pointer _
std::__uninitialized_allocator_relocate(
this->__layout_.__alloc(), std::__to_address(__layout_.__begin_ptr()), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
- __layout_.__set_boundary(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ __layout_.__set_boundary(__layout_.__zero_relative_to_begin()); // All the objects have been destroyed by relocating them.
__layout_.__swap_layouts(__v);
__v.__set_data(__v.begin());
@@ -912,8 +919,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOE
clear();
__annotate_delete();
__alloc_traits::deallocate(this->__layout_.__alloc(), this->__layout_.__begin_ptr(), capacity());
- __layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
- __layout_.__set_capacity(static_cast<size_type>(0));
+ __layout_.__reset_without_allocator();
}
}
@@ -979,8 +985,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
: __layout_(std::move(__x.__layout_.__alloc())) {
__layout_.__set_valid_range(__x.__layout_.__begin_ptr(), __x.__layout_.__boundary_representation());
__layout_.__set_capacity(__x.__layout_.__capacity_representation());
- __x.__layout_.__set_valid_range(nullptr, static_cast<size_type>(0));
- __x.__layout_.__set_capacity(static_cast<size_type>(0));
+ __x.__layout_.__reset_without_allocator();
}
template <class _Tp, class _Allocator>
>From d27d411c8c84dbddea1efefa04e62e7c6666021b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 11 Feb 2026 05:10:33 +0000
Subject: [PATCH 34/39] moves `__swap_out_circular_buffer` to `__vector_layout`
---
libcxx/include/__vector/layout.h | 108 +++++++++++++++++++++++++++++++
libcxx/include/__vector/vector.h | 91 ++++++--------------------
2 files changed, 126 insertions(+), 73 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 98eccdaa9c8b8..7cc211a8b7a95 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -11,9 +11,12 @@
#include <__assert>
#include <__config>
+#include <__debug_utils/sanitizers.h>
#include <__memory/allocator_traits.h>
#include <__memory/compressed_pair.h>
+#include <__memory/pointer_traits.h>
#include <__memory/swap_allocator.h>
+#include <__memory/uninitialized_algorithms.h>
#include <__split_buffer>
#include <__type_traits/is_nothrow_constructible.h>
#include <__utility/move.h>
@@ -169,6 +172,11 @@ class __vector_layout {
return __begin_;
}
+ /// Returns a built-in pointer to the beginning of the buffer.
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp* __data() _NOEXCEPT { return std::__to_address(__begin_); }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const* const __data() const _NOEXCEPT { return std::__to_address(__begin_); }
+
/// Returns the value that the layout uses to determine the vector's size.
///
/// `__boundary_representation()` should only be used when directly operating on the layout from
@@ -237,6 +245,21 @@ class __vector_layout {
__other.__reset_without_allocator();
}
+ /// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
+ /// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
+ /// exactly `__size()` objects in the front. This function has a strong exception guarantee.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(_SplitBuffer& __buffer) {
+ __annotate_delete();
+ auto __relocation_begin = __buffer.begin() - __size();
+ std::__uninitialized_allocator_relocate(__alloc_, std::__to_address(__begin_), std::__to_address(__end_ptr()), std::__to_address(__relocation_begin));
+ __buffer.__set_valid_range(__relocation_begin, __buffer.end());
+ __set_boundary(__zero_relative_to_begin());
+
+ __swap_layouts(__buffer);
+ __buffer.__set_data(__buffer.begin());
+ __annotate_new(__size());
+ }
+
// Methods below this line must be implemented per vector layout.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __size() const _NOEXCEPT;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __capacity() const _NOEXCEPT;
@@ -252,6 +275,14 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_boundary(pointer __ptr) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __n) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __ptr) _NOEXCEPT;
+
+ /// `__relocate_with_pivot` relocates the objects in `[__begin_, __p)` into the front of `__buffer`,
+ /// the objects in `[__p, end())` into the back of `__buffer` and swaps the buffers of `*this` and
+ /// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
+ /// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
+ /// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(_SplitBuffer& __buffer, pointer __p);
+
/// Returns `__begin_` if `__boundary_type` is `pointer`, and `0` if it is `size_type`.
///
/// Since `0` is implicitly convertible to both `size_type` and `nullptr`, `__set_boundary(0)` is
@@ -276,6 +307,19 @@ class __vector_layout {
pointer __boundary_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __capacity_, allocator_type, __alloc_);
#endif
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
+ std::__annotate_contiguous_container<_Allocator>(__data(), __data() + __capacity(), __old_mid, __new_mid);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_new(size_type __current_size) const _NOEXCEPT {
+ __annotate_contiguous_container(__data() + __capacity(), __data() + __current_size);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
+ __annotate_contiguous_container(__data() + __size(), __data() + __capacity());
+ }
};
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -367,6 +411,39 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return 0;
}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout<_Tp, _Alloc>::pointer __vector_layout<_Tp, _Alloc>::__relocate_with_pivot(_SplitBuffer& __buffer, pointer __p)
+{
+ __annotate_delete();
+ pointer __result = __buffer.begin();
+ pointer __end = __end_ptr();
+
+ // We relocate elements in reverse order to ensure that a throwing relocation operation leaves the
+ // vector in a valid state.
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__p),
+ std::__to_address(__end),
+ std::__to_address(__buffer.end()));
+ auto __relocated_so_far = __end - __p;
+ __buffer.__set_sentinel(__buffer.size() + __relocated_so_far);
+ __boundary_ -= __relocated_so_far; // The objects in [__p, __boundary_) have been destroyed by relocating them.
+ auto __new_begin = __buffer.begin() - __boundary_;
+
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__begin_),
+ std::__to_address(__p),
+ std::__to_address(__new_begin));
+ __buffer.__set_valid_range(__new_begin, __buffer.size() + __boundary_);
+ __boundary_ = 0; // All the objects have been destroyed by relocating them.
+
+ __swap_layouts(__buffer);
+ __buffer.__set_data(__buffer.begin());
+ __annotate_new(__boundary_);
+ return __result;
+}
#else
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -460,6 +537,37 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return nullptr;
}
+
+template <class _Tp, class _Alloc>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout<_Tp, _Alloc>::pointer __vector_layout<_Tp, _Alloc>::__relocate_with_pivot(_SplitBuffer& __buffer, pointer __p)
+{
+ __annotate_delete();
+ pointer __ret = __buffer.begin();
+
+ // Relocate [__p, __boundary_) first to avoid having a hole in [__begin_, __boundary_)
+ // in case something in [__begin_, __p) throws.
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__p),
+ std::__to_address(__boundary_),
+ std::__to_address(__buffer.end()));
+ auto __relocated_so_far = __boundary_ - __p;
+ __buffer.__set_sentinel(__buffer.end() + __relocated_so_far);
+ __boundary_ = __p; // The objects in [__p, __boundary_) have been destroyed by relocating them.
+ auto __new_begin = __buffer.begin() - (__p - __begin_);
+
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__begin_),
+ std::__to_address(__p),
+ std::__to_address(__new_begin));
+ __buffer.__set_valid_range(__new_begin, __buffer.end());
+ __boundary_ = __begin_; // All the objects have been destroyed by relocating them.
+ __swap_layouts(__buffer);
+ __buffer.__set_data(__buffer.begin());
+ __annotate_new(__size());
+ return __ret;
+}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 796d09eec4075..dc34048ac5bcb 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -451,11 +451,11 @@ class vector {
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(this->__layout_.__begin_ptr());
+ return __layout_.__data();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(this->__layout_.__begin_ptr());
+ return __layout_.__data();
}
//
@@ -492,7 +492,7 @@ class vector {
} else {
_SplitBuffer __buffer(__recommend(size() + __len), size(), __layout_.__alloc());
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
- __swap_out_circular_buffer(__buffer);
+ __layout_.__relocate(__buffer);
}
} else {
vector __buffer(__layout_.__alloc());
@@ -575,7 +575,7 @@ class vector {
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
#endif
- bool __invariants() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT {
return __layout_.__invariants();
}
@@ -592,9 +592,9 @@ class vector {
// Postcondition: capacity() >= __n
// Postcondition: size() == 0
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
- _LIBCPP_ASSERT_INTERNAL(__layout_.begin() == nullptr, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's begin pointer.");
- _LIBCPP_ASSERT_INTERNAL(__layout_.empty(), "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's size.");
- _LIBCPP_ASSERT_INTERNAL(capacity() == 0, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's capacity.");
+ _LIBCPP_ASSERT_INTERNAL(__layout_.__begin_ptr() == nullptr, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's begin pointer.");
+ _LIBCPP_ASSERT_INTERNAL(__layout_.__empty(), "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's size.");
+ _LIBCPP_ASSERT_INTERNAL(__layout_.__capacity() == 0, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's capacity.");
_LIBCPP_ASSERT_INTERNAL(__n > 0, "vector::__vallocate cannot allocate 0 bytes");
if (__n > max_size())
@@ -715,9 +715,6 @@ class vector {
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(_SplitBuffer& __v);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(_SplitBuffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -861,58 +858,6 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__layout_.__begin_ptr(), size()) into the front of __v and swaps the
-// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
-// function has a strong exception guarantee.
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v) {
- __annotate_delete();
- auto __new_begin = __v.begin() - size();
- std::__uninitialized_allocator_relocate(
- this->__layout_.__alloc(),
- std::__to_address(__layout_.__begin_ptr()),
- std::__to_address(__layout_.__end_ptr()),
- std::__to_address(__new_begin));
- __v.__set_valid_range(__new_begin, __v.end());
- __layout_.__set_boundary(__layout_.__zero_relative_to_begin()); // All the objects have been destroyed by relocating them.
-
- __layout_.__swap_layouts(__v);
- __v.__set_data(__v.begin());
- __annotate_new(size());
-}
-
-// __swap_out_circular_buffer relocates the objects in [__layout_.__begin_ptr(), __p) into the front of __v, the objects in
-// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __layout_.__begin_ptr()) objects in the front and space for at least (size() - __p) objects in the back. This
-// function has a strong exception guarantee if __layout_.__begin_ptr() == __p || size() == __p.
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(_SplitBuffer& __v, pointer __p) {
- __annotate_delete();
- pointer __ret = __v.begin();
-
- pointer __end = __layout_.__end_ptr();
- // Relocate [__p, __end) first to avoid having a hole in [__layout_.__begin_ptr(), __end)
- // in case something in [__layout_.__begin_ptr(), __p) throws.
- std::__uninitialized_allocator_relocate(
- this->__layout_.__alloc(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
- auto __relocated_so_far = __end - __p;
- __v.__set_sentinel(__v.end() + __relocated_so_far);
- __layout_.__set_boundary(__layout_.__boundary_representation() -
- __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __layout_.__begin_ptr());
-
- std::__uninitialized_allocator_relocate(
- this->__layout_.__alloc(), std::__to_address(__layout_.__begin_ptr()), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__set_valid_range(__new_begin, __v.size() + size());
- __layout_.__set_boundary(__layout_.__zero_relative_to_begin()); // All the objects have been destroyed by relocating them.
-
- __layout_.__swap_layouts(__v);
- __v.__set_data(__v.begin());
- __annotate_new(size());
- return __ret;
-}
-
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
if (this->__layout_.__begin_ptr() != nullptr) {
@@ -1087,7 +1032,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > max_size())
this->__throw_length_error();
_SplitBuffer __v(__n, size(), this->__layout_.__alloc());
- __swap_out_circular_buffer(__v);
+ __layout_.__relocate(__v);
}
}
@@ -1102,7 +1047,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
if (__v.capacity() < capacity())
- __swap_out_circular_buffer(__v);
+ __layout_.__relocate(__v);
#if _LIBCPP_HAS_EXCEPTIONS
} catch (...) {
}
@@ -1119,7 +1064,7 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
pointer __end = __v.end();
__alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
- __swap_out_circular_buffer(__v);
+ __layout_.__relocate(__v);
return __layout_.__boundary_representation();
}
@@ -1220,7 +1165,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
} else {
_SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(__x);
- __p = __swap_out_circular_buffer(__v, __p);
+ __p = __layout_.__relocate_with_pivot(__v, __p);
}
return __make_iter(__p);
}
@@ -1240,7 +1185,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
} else {
_SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(std::move(__x));
- __p = __swap_out_circular_buffer(__v, __p);
+ __p = __layout_.__relocate_with_pivot(__v, __p);
}
return __make_iter(__p);
}
@@ -1262,7 +1207,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
} else {
_SplitBuffer __v(__recommend(size() + 1), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.emplace_back(std::forward<_Args>(__args)...);
- __p = __swap_out_circular_buffer(__v, __p);
+ __p = __layout_.__relocate_with_pivot(__v, __p);
}
return __make_iter(__p);
}
@@ -1291,7 +1236,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
} else {
_SplitBuffer __v(__recommend(size() + __n), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.__construct_at_end(__n, __x);
- __p = __swap_out_circular_buffer(__v, __p);
+ __p = __layout_.__relocate_with_pivot(__v, __p);
}
}
return __make_iter(__p);
@@ -1327,7 +1272,7 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__layout_.__alloc(), std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
- __p = __swap_out_circular_buffer(__merged, __p);
+ __p = __layout_.__relocate_with_pivot(__merged, __p);
}
return __make_iter(__p);
}
@@ -1365,7 +1310,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
} else {
_SplitBuffer __v(__recommend(size() + __n), __p - this->__layout_.__begin_ptr(), this->__layout_.__alloc());
__v.__construct_at_end_with_size(std::move(__first), __n);
- __p = __swap_out_circular_buffer(__v, __p);
+ __p = __layout_.__relocate_with_pivot(__v, __p);
}
}
return __make_iter(__p);
@@ -1380,7 +1325,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
} else {
_SplitBuffer __v(__recommend(__new_size), __current_size, __layout_.__alloc());
__v.__construct_at_end(__new_size - __current_size);
- __swap_out_circular_buffer(__v);
+ __layout_.__relocate(__v);
}
} else if (__current_size > __new_size) {
this->__destruct_at_end(this->__layout_.__begin_ptr() + __new_size);
@@ -1396,7 +1341,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
else {
_SplitBuffer __v(__recommend(__new_size), __current_size, __layout_.__alloc());
__v.__construct_at_end(__new_size - __current_size, __x);
- __swap_out_circular_buffer(__v);
+ __layout_.__relocate(__v);
}
} else if (__current_size > __new_size) {
this->__destruct_at_end(this->__layout_.__begin_ptr() + __new_size);
>From e303197de7d1a00a0e0a7cfca1679030cb0421d7 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 11 Feb 2026 08:09:21 +0000
Subject: [PATCH 35/39] moves `__relocate` to `__split_buffer`
---
libcxx/include/__split_buffer | 110 +++++++++++++++++++++++++++++++
libcxx/include/__vector/layout.h | 86 ++----------------------
2 files changed, 117 insertions(+), 79 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1332f89c078fc..d8ca8a8186707 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -25,6 +25,7 @@
#include <__memory/compressed_pair.h>
#include <__memory/pointer_traits.h>
#include <__memory/swap_allocator.h>
+#include <__memory/uninitialized_algorithms.h>
#include <__type_traits/conditional.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
@@ -195,6 +196,58 @@ public:
std::swap(__back_cap_, __back_capacity);
}
+ /// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
+ /// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
+ /// exactly `__size()` objects in the front. This function has a strong exception guarantee.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(pointer& __first, pointer& __last, pointer& __capacity) {
+ auto __size = __last - __first;
+ auto __new_begin = __begin_ - __size;
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__first),
+ std::__to_address(__last),
+ std::__to_address(__new_begin));
+ __begin_ = __new_begin;
+ __last = __first;
+
+ __swap_layouts(__first, __last, __capacity);
+ __front_cap_ = __begin_;
+ }
+
+ /// `__relocate_with_pivot` relocates the objects in `[__begin_, __p)` into the front of `__buffer`,
+ /// the objects in `[__p, end())` into the back of `__buffer` and swaps the buffers of `*this` and
+ /// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
+ /// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
+ /// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(pointer __pivot, pointer& __first, pointer& __last, pointer& __capacity)
+ {
+ pointer __result = __begin_;
+
+ // Relocate [__p, __last) first to avoid having a hole in [__first, __last)
+ // in case something in [__first, __p) throws.
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__pivot),
+ std::__to_address(__last),
+ std::__to_address(__end_));
+ auto __relocated_so_far = __last - __pivot;
+ __end_ += __relocated_so_far;
+ __last = __pivot; // The objects in [__p, __last) have been destroyed by relocating them.
+
+ auto __new_begin = __begin_ - (__pivot - __first);
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__first),
+ std::__to_address(__pivot),
+ std::__to_address(__new_begin));
+ __begin_ = __new_begin;
+
+ __last = __first; // All the objects have been destroyed by relocating them.
+ __swap_layouts(__first, __last, __capacity);
+ __front_cap_ = __begin_;
+ return __result;
+ }
+
private:
pointer __front_cap_ = nullptr;
pointer __begin_ = nullptr;
@@ -350,6 +403,61 @@ public:
std::swap(__cap_, __capacity);
}
+ /// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
+ /// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
+ /// exactly `__size()` objects in the front. This function has a strong exception guarantee.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(pointer& __first, size_type& __n, size_type& __capacity) {
+ auto __new_begin = __begin_ - __n;
+ auto __last = __first + __n;
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__first),
+ std::__to_address(__last),
+ std::__to_address(__new_begin));
+ __set_valid_range(__new_begin, end());
+ __n = 0;
+
+ __swap_layouts(__first, __n, __capacity);
+ __front_cap_ = __begin_;
+ }
+
+ /// `__relocate_with_pivot` relocates the objects in `[__begin_, __p)` into the front of `__buffer`,
+ /// the objects in `[__p, end())` into the back of `__buffer` and swaps the buffers of `*this` and
+ /// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
+ /// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
+ /// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(pointer __pivot, pointer& __first, size_type& __n, size_type& __capacity)
+ {
+ pointer __result = __begin_;
+ pointer __last = __first + __n;
+
+ // We relocate elements in reverse order to ensure that a throwing relocation operation leaves the
+ // buffer in a valid state.
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__pivot),
+ std::__to_address(__last),
+ std::__to_address(end()));
+
+ auto const __relocated_so_far = __last - __pivot;
+ __size_ += __relocated_so_far;
+ __n -= __relocated_so_far; // The objects in [__pivot, __last) have been destroyed by relocating them.
+
+ auto __new_begin = __begin_ - __n;
+ std::__uninitialized_allocator_relocate(
+ __alloc_,
+ std::__to_address(__first),
+ std::__to_address(__pivot),
+ std::__to_address(__new_begin));
+ __begin_ = __new_begin;
+ __size_ += __n;
+ __n = 0; // All the objects have been destroyed by relocating them.
+
+ __swap_layouts(__first, __n, __capacity);
+ __front_cap_ = __begin_;
+ return __result;
+ }
+
private:
pointer __front_cap_ = nullptr;
pointer __begin_ = nullptr;
@@ -456,6 +564,8 @@ public:
using __base_type::__get_allocator;
using __base_type::__raw_capacity;
using __base_type::__raw_sentinel;
+ using __base_type::__relocate;
+ using __base_type::__relocate_with_pivot;
using __base_type::__reset;
using __base_type::__set_capacity;
using __base_type::__set_data;
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 7cc211a8b7a95..d22e8a6c1af2d 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -245,19 +245,17 @@ class __vector_layout {
__other.__reset_without_allocator();
}
- /// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
- /// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
- /// exactly `__size()` objects in the front. This function has a strong exception guarantee.
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(_SplitBuffer& __buffer) {
__annotate_delete();
- auto __relocation_begin = __buffer.begin() - __size();
- std::__uninitialized_allocator_relocate(__alloc_, std::__to_address(__begin_), std::__to_address(__end_ptr()), std::__to_address(__relocation_begin));
- __buffer.__set_valid_range(__relocation_begin, __buffer.end());
- __set_boundary(__zero_relative_to_begin());
+ __buffer.__relocate(__begin_, __boundary_, __capacity_);
+ __annotate_new(__size());
+ }
- __swap_layouts(__buffer);
- __buffer.__set_data(__buffer.begin());
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(_SplitBuffer& __buffer, pointer __pivot) {
+ __annotate_delete();
+ auto __result = __buffer.__relocate_with_pivot(__pivot, __begin_, __boundary_, __capacity_);
__annotate_new(__size());
+ return __result;
}
// Methods below this line must be implemented per vector layout.
@@ -276,12 +274,6 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __n) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __ptr) _NOEXCEPT;
- /// `__relocate_with_pivot` relocates the objects in `[__begin_, __p)` into the front of `__buffer`,
- /// the objects in `[__p, end())` into the back of `__buffer` and swaps the buffers of `*this` and
- /// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
- /// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
- /// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(_SplitBuffer& __buffer, pointer __p);
/// Returns `__begin_` if `__boundary_type` is `pointer`, and `0` if it is `size_type`.
///
@@ -411,39 +403,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return 0;
}
-
-template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout<_Tp, _Alloc>::pointer __vector_layout<_Tp, _Alloc>::__relocate_with_pivot(_SplitBuffer& __buffer, pointer __p)
-{
- __annotate_delete();
- pointer __result = __buffer.begin();
- pointer __end = __end_ptr();
-
- // We relocate elements in reverse order to ensure that a throwing relocation operation leaves the
- // vector in a valid state.
- std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__p),
- std::__to_address(__end),
- std::__to_address(__buffer.end()));
- auto __relocated_so_far = __end - __p;
- __buffer.__set_sentinel(__buffer.size() + __relocated_so_far);
- __boundary_ -= __relocated_so_far; // The objects in [__p, __boundary_) have been destroyed by relocating them.
- auto __new_begin = __buffer.begin() - __boundary_;
-
- std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__begin_),
- std::__to_address(__p),
- std::__to_address(__new_begin));
- __buffer.__set_valid_range(__new_begin, __buffer.size() + __boundary_);
- __boundary_ = 0; // All the objects have been destroyed by relocating them.
-
- __swap_layouts(__buffer);
- __buffer.__set_data(__buffer.begin());
- __annotate_new(__boundary_);
- return __result;
-}
#else
template <class _Tp, class _Alloc>
_LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -537,37 +496,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __vector_layout<_Tp
__vector_layout<_Tp, _Alloc>::__zero_boundary_type() _NOEXCEPT {
return nullptr;
}
-
-template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout<_Tp, _Alloc>::pointer __vector_layout<_Tp, _Alloc>::__relocate_with_pivot(_SplitBuffer& __buffer, pointer __p)
-{
- __annotate_delete();
- pointer __ret = __buffer.begin();
-
- // Relocate [__p, __boundary_) first to avoid having a hole in [__begin_, __boundary_)
- // in case something in [__begin_, __p) throws.
- std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__p),
- std::__to_address(__boundary_),
- std::__to_address(__buffer.end()));
- auto __relocated_so_far = __boundary_ - __p;
- __buffer.__set_sentinel(__buffer.end() + __relocated_so_far);
- __boundary_ = __p; // The objects in [__p, __boundary_) have been destroyed by relocating them.
- auto __new_begin = __buffer.begin() - (__p - __begin_);
-
- std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__begin_),
- std::__to_address(__p),
- std::__to_address(__new_begin));
- __buffer.__set_valid_range(__new_begin, __buffer.end());
- __boundary_ = __begin_; // All the objects have been destroyed by relocating them.
- __swap_layouts(__buffer);
- __buffer.__set_data(__buffer.begin());
- __annotate_new(__size());
- return __ret;
-}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
_LIBCPP_END_NAMESPACE_STD
>From 30ff479abbfa6c2bba32aeba5a675565ba6b37b4 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 11 Feb 2026 08:31:26 +0000
Subject: [PATCH 36/39] replaces __set_valid_range with __set_layout
---
libcxx/include/__vector/layout.h | 11 +++--------
libcxx/include/__vector/vector.h | 17 ++---------------
2 files changed, 5 insertions(+), 23 deletions(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index d22e8a6c1af2d..36d049065c2d7 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -208,15 +208,11 @@ class __vector_layout {
return __boundary_ == __capacity_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_layout(pointer __new_begin, size_type __new_size, size_type __new_capacity) _NOEXCEPT
+ {
__begin_ = __new_begin;
__set_boundary(__new_size);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
- __begin_ = __new_begin;
- __set_boundary(__new_end);
+ __set_capacity(__new_capacity);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset_without_allocator() _NOEXCEPT
@@ -274,7 +270,6 @@ class __vector_layout {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __n) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __ptr) _NOEXCEPT;
-
/// Returns `__begin_` if `__boundary_type` is `pointer`, and `0` if it is `size_type`.
///
/// Since `0` is implicitly convertible to both `size_type` and `nullptr`, `__set_boundary(0)` is
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index dc34048ac5bcb..0500648bc253b 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -600,16 +600,7 @@ class vector {
if (__n > max_size())
this->__throw_length_error();
auto __allocation = std::__allocate_at_least(this->__layout_.__alloc(), __n);
- // Since the pointer-based `__layout_.__zero_relative_to_begin()` returns a pointer to the
- // memory that it currently holds, we can't use it when changing `__layout_.__begin_`. As such,
- // we need to tell the layout that we want our layout to point to `__allocation.ptr`, and for it
- // to be empty.
- //
- // We explicitly convert `0` to `size_type` to prevent ambiguity between `__vector_layout's`
- // pointer-based and size-based `__set_valid_range` overloads, as `0` is implicitly convertible
- // to `size_type`.
- __layout_.__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
- __layout_.__set_capacity(__allocation.count);
+ __layout_.__set_layout(__allocation.ptr, 0, __allocation.count);
__annotate_new(0);
}
@@ -927,11 +918,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __layout_(std::move(__x.__layout_.__alloc())) {
- __layout_.__set_valid_range(__x.__layout_.__begin_ptr(), __x.__layout_.__boundary_representation());
- __layout_.__set_capacity(__x.__layout_.__capacity_representation());
- __x.__layout_.__reset_without_allocator();
-}
+ : __layout_(std::move(__x.__layout_)) {}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
>From 2cde38d59c8b400f0eb00a16ec112ea8f4e5177a Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 11 Feb 2026 08:33:15 +0000
Subject: [PATCH 37/39] clang-format fix
---
libcxx/include/__split_buffer | 56 ++++++++++++--------------------
libcxx/include/__vector/layout.h | 34 +++++++++++--------
libcxx/include/__vector/vector.h | 41 ++++++++++++++++-------
3 files changed, 70 insertions(+), 61 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index d8ca8a8186707..bb9551d50ebf2 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -199,16 +199,14 @@ public:
/// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
/// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
/// exactly `__size()` objects in the front. This function has a strong exception guarantee.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(pointer& __first, pointer& __last, pointer& __capacity) {
- auto __size = __last - __first;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __relocate(pointer& __first, pointer& __last, pointer& __capacity) {
+ auto __size = __last - __first;
auto __new_begin = __begin_ - __size;
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__first),
- std::__to_address(__last),
- std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__first), std::__to_address(__last), std::__to_address(__new_begin));
__begin_ = __new_begin;
- __last = __first;
+ __last = __first;
__swap_layouts(__first, __last, __capacity);
__front_cap_ = __begin_;
@@ -219,27 +217,21 @@ public:
/// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
/// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
/// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(pointer __pivot, pointer& __first, pointer& __last, pointer& __capacity)
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
+ __relocate_with_pivot(pointer __pivot, pointer& __first, pointer& __last, pointer& __capacity) {
pointer __result = __begin_;
// Relocate [__p, __last) first to avoid having a hole in [__first, __last)
// in case something in [__first, __p) throws.
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__pivot),
- std::__to_address(__last),
- std::__to_address(__end_));
+ __alloc_, std::__to_address(__pivot), std::__to_address(__last), std::__to_address(__end_));
auto __relocated_so_far = __last - __pivot;
__end_ += __relocated_so_far;
- __last = __pivot; // The objects in [__p, __last) have been destroyed by relocating them.
+ __last = __pivot; // The objects in [__p, __last) have been destroyed by relocating them.
auto __new_begin = __begin_ - (__pivot - __first);
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__first),
- std::__to_address(__pivot),
- std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__first), std::__to_address(__pivot), std::__to_address(__new_begin));
__begin_ = __new_begin;
__last = __first; // All the objects have been destroyed by relocating them.
@@ -406,14 +398,12 @@ public:
/// `__relocate` relocates the objects in `[__begin_, __size())` into the front of `__buffer` and
/// swaps the buffers of `*this` and `__buffer`. It is assumed that `__buffer` provides space for
/// exactly `__size()` objects in the front. This function has a strong exception guarantee.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __relocate(pointer& __first, size_type& __n, size_type& __capacity) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __relocate(pointer& __first, size_type& __n, size_type& __capacity) {
auto __new_begin = __begin_ - __n;
- auto __last = __first + __n;
+ auto __last = __first + __n;
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__first),
- std::__to_address(__last),
- std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__first), std::__to_address(__last), std::__to_address(__new_begin));
__set_valid_range(__new_begin, end());
__n = 0;
@@ -426,29 +416,23 @@ public:
/// `__buffer`. It is assumed that `__buffer` provides space for exactly `(__p - __begin_ptr())`
/// objects in the front and space for at least `(__size() - __p)` objects in the back. This function
/// has a strong exception guarantee if `__begin_ == __p || __size() == __p`.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(pointer __pivot, pointer& __first, size_type& __n, size_type& __capacity)
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
+ __relocate_with_pivot(pointer __pivot, pointer& __first, size_type& __n, size_type& __capacity) {
pointer __result = __begin_;
- pointer __last = __first + __n;
+ pointer __last = __first + __n;
// We relocate elements in reverse order to ensure that a throwing relocation operation leaves the
// buffer in a valid state.
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__pivot),
- std::__to_address(__last),
- std::__to_address(end()));
+ __alloc_, std::__to_address(__pivot), std::__to_address(__last), std::__to_address(end()));
auto const __relocated_so_far = __last - __pivot;
__size_ += __relocated_so_far;
- __n -= __relocated_so_far; // The objects in [__pivot, __last) have been destroyed by relocating them.
+ __n -= __relocated_so_far; // The objects in [__pivot, __last) have been destroyed by relocating them.
auto __new_begin = __begin_ - __n;
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__first),
- std::__to_address(__pivot),
- std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__first), std::__to_address(__pivot), std::__to_address(__new_begin));
__begin_ = __new_begin;
__size_ += __n;
__n = 0; // All the objects have been destroyed by relocating them.
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 36d049065c2d7..3510f4c60181e 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -173,9 +173,13 @@ class __vector_layout {
}
/// Returns a built-in pointer to the beginning of the buffer.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp* __data() _NOEXCEPT { return std::__to_address(__begin_); }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp* __data() _NOEXCEPT {
+ return std::__to_address(__begin_);
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const* const __data() const _NOEXCEPT { return std::__to_address(__begin_); }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const* const __data() const _NOEXCEPT {
+ return std::__to_address(__begin_);
+ }
/// Returns the value that the layout uses to determine the vector's size.
///
@@ -208,15 +212,14 @@ class __vector_layout {
return __boundary_ == __capacity_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_layout(pointer __new_begin, size_type __new_size, size_type __new_capacity) _NOEXCEPT
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_layout(pointer __new_begin, size_type __new_size, size_type __new_capacity) _NOEXCEPT {
__begin_ = __new_begin;
__set_boundary(__new_size);
__set_capacity(__new_capacity);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset_without_allocator() _NOEXCEPT
- {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset_without_allocator() _NOEXCEPT {
__begin_ = nullptr;
__set_boundary(__zero_relative_to_begin());
__set_capacity(__zero_relative_to_begin());
@@ -233,7 +236,8 @@ class __vector_layout {
__other.__swap_layouts(__begin_, __boundary_, __capacity_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_without_allocator(__vector_layout& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __move_without_allocator(__vector_layout& __other) _NOEXCEPT {
__begin_ = __other.__begin_;
__boundary_ = __other.__boundary_;
__capacity_ = __other.__capacity_;
@@ -247,7 +251,8 @@ class __vector_layout {
__annotate_new(__size());
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __relocate_with_pivot(_SplitBuffer& __buffer, pointer __pivot) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
+ __relocate_with_pivot(_SplitBuffer& __buffer, pointer __pivot) {
__annotate_delete();
auto __result = __buffer.__relocate_with_pivot(__pivot, __begin_, __boundary_, __capacity_);
__annotate_new(__size());
@@ -278,7 +283,8 @@ class __vector_layout {
/// pointer arithmetic in the pointer-based `__set_boundary(size_type{})`.
///
/// Note that this function cannot be used when setting `__begin_`.
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __boundary_type __zero_relative_to_begin() _NOEXCEPT;
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __boundary_type
+ __zero_relative_to_begin() _NOEXCEPT;
// Works around a Clang 20 zero-initialization bug on user-defined pointer types.
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static __boundary_type
__zero_boundary_type() _NOEXCEPT;
@@ -295,8 +301,8 @@ class __vector_layout {
_LIBCPP_COMPRESSED_PAIR(pointer, __capacity_, allocator_type, __alloc_);
#endif
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20
+ _LIBCPP_HIDE_FROM_ABI void __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
std::__annotate_contiguous_container<_Allocator>(__data(), __data() + __capacity(), __old_mid, __new_mid);
}
@@ -389,7 +395,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type
+__vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
return 0;
}
@@ -482,7 +489,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vector_layout<_Tp, _Alloc>::__set_capacity(
}
template <class _Tp, class _Alloc>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type __vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename __vector_layout<_Tp, _Alloc>::__boundary_type
+__vector_layout<_Tp, _Alloc>::__zero_relative_to_begin() _NOEXCEPT {
return __begin_;
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 0500648bc253b..05d75351497f4 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -134,7 +134,7 @@ class vector {
// [vector.cons], construct/copy/destroy
//
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a)
#if _LIBCPP_STD_VER <= 14
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
@@ -478,7 +478,8 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(
+ this->__layout_.__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -592,9 +593,18 @@ class vector {
// Postcondition: capacity() >= __n
// Postcondition: size() == 0
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
- _LIBCPP_ASSERT_INTERNAL(__layout_.__begin_ptr() == nullptr, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's begin pointer.");
- _LIBCPP_ASSERT_INTERNAL(__layout_.__empty(), "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's size.");
- _LIBCPP_ASSERT_INTERNAL(__layout_.__capacity() == 0, "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already owns a buffer, or a deallocation function didn't reset the layout's capacity.");
+ _LIBCPP_ASSERT_INTERNAL(
+ __layout_.__begin_ptr() == nullptr,
+ "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already "
+ "owns a buffer, or a deallocation function didn't reset the layout's begin pointer.");
+ _LIBCPP_ASSERT_INTERNAL(
+ __layout_.__empty(),
+ "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already "
+ "owns a buffer, or a deallocation function didn't reset the layout's size.");
+ _LIBCPP_ASSERT_INTERNAL(
+ __layout_.__capacity() == 0,
+ "vector::__vallocate can only be called on a vector that hasn't allocated memory. This vector either already "
+ "owns a buffer, or a deallocation function didn't reset the layout's capacity.");
_LIBCPP_ASSERT_INTERNAL(__n > 0, "vector::__vallocate cannot allocate 0 bytes");
if (__n > max_size())
@@ -907,8 +917,8 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ =
- std::__uninitialized_allocator_copy(this->__layout_.__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ = std::__uninitialized_allocator_copy(
+ this->__layout_.__alloc(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -918,7 +928,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __layout_(std::move(__x.__layout_)) {}
+ : __layout_(std::move(__x.__layout_)) {
+}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
@@ -1250,13 +1261,19 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
_SplitBuffer __merged(
__recommend(size() + __v.size()), __off, __layout_.__alloc()); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __layout_.__alloc(), std::__to_address(__old_last), std::__to_address(__layout_.__end_ptr()), std::__to_address(__merged.end()));
- __guard.__complete(); // Release the guard once objects in [__old_last_, __layout_.__end_ptr()) have been successfully
- // relocated.
+ __layout_.__alloc(),
+ std::__to_address(__old_last),
+ std::__to_address(__layout_.__end_ptr()),
+ std::__to_address(__merged.end()));
+ __guard.__complete(); // Release the guard once objects in [__old_last_, __layout_.__end_ptr()) have been
+ // successfully relocated.
__merged.__set_sentinel(__merged.end() + (__layout_.__end_ptr() - __old_last));
__layout_.__set_boundary(__old_last);
std::__uninitialized_allocator_relocate(
- __layout_.__alloc(), std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __layout_.__alloc(),
+ std::__to_address(__v.begin()),
+ std::__to_address(__v.end()),
+ std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __layout_.__relocate_with_pivot(__merged, __p);
>From 42581964a42009a66f59be9d6933b80e23320aff Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 11 Feb 2026 21:40:10 +0000
Subject: [PATCH 38/39] removes unnecessary const-qualifier
---
libcxx/include/__vector/layout.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__vector/layout.h b/libcxx/include/__vector/layout.h
index 3510f4c60181e..6d865eb87f4cf 100644
--- a/libcxx/include/__vector/layout.h
+++ b/libcxx/include/__vector/layout.h
@@ -177,7 +177,7 @@ class __vector_layout {
return std::__to_address(__begin_);
}
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const* const __data() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _Tp const* __data() const _NOEXCEPT {
return std::__to_address(__begin_);
}
>From d83c65266b7e7fe4eca68467d507ff8a00404ba0 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 6 Mar 2026 19:16:03 +0000
Subject: [PATCH 39/39] fixes who accesses `__capacity_ptr()`
---
libcxx/include/__vector/vector.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 05d75351497f4..77aeabe2c3d54 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -698,7 +698,7 @@ class vector {
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
std::__wrap_iter<pointer>(this->__layout_.__begin_ptr()),
- std::__wrap_iter<pointer>(this->__capacity_ptr()));
+ std::__wrap_iter<pointer>(this->__layout_.__capacity_ptr()));
#else
return iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -710,7 +710,7 @@ class vector {
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
std::__wrap_iter<const_pointer>(this->__layout_.__begin_ptr()),
- std::__wrap_iter<const_pointer>(this->__capacity_ptr()));
+ std::__wrap_iter<const_pointer>(this->__layout_.__capacity_ptr()));
#else
return const_iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
More information about the libcxx-commits
mailing list