[libcxx-commits] [libcxx] [lldb] [libcxx] adds size-based `__split_buffer` representation to unstable ABI (PR #139632)
Christopher Di Bella via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Aug 20 13:57:29 PDT 2025
https://github.com/cjdb updated https://github.com/llvm/llvm-project/pull/139632
>From 88bc35049f774c8c3a5c35ff22470a0670ee3e9d Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 7 May 2025 20:41:56 +0000
Subject: [PATCH 01/28] [libcxx] adds size-based `__split_buffer`
representation to 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.
`vector` depends on `__split_buffer` for inserting elements. Changing
`__split_buffer` to match `vector`'s representation simplifies the
model, as it eliminates the need to convert between two different
representations of a contiguous buffer in the same configuration of
libc++.
[RFC]: TODO
---
libcxx/include/__split_buffer | 549 +++++++++++++++++++++----------
libcxx/include/__vector/vector.h | 48 +--
libcxx/include/deque | 40 +--
3 files changed, 416 insertions(+), 221 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 21e58f4abc6b3..9710dfec774f7 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -13,10 +13,12 @@
#include <__algorithm/max.h>
#include <__algorithm/move.h>
#include <__algorithm/move_backward.h>
+#include <__assert>
#include <__config>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/move_iterator.h>
+#include <__memory/addressof.h>
#include <__memory/allocate_at_least.h>
#include <__memory/allocator.h>
#include <__memory/allocator_traits.h>
@@ -78,23 +80,260 @@ public:
__split_buffer,
void>;
- pointer __first_;
- pointer __begin_;
- pointer __end_;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
+ struct __data {
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
+#ifndef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+#else
+ size_type __size_ = 0;
+ _LIBCPP_COMPRESSED_PAIR(size_type, __cap_ = 0, allocator_type, __alloc_);
+#endif
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __data() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __data(const allocator_type& __alloc)
+ : __alloc_(__alloc)
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() noexcept {
+ return __first_;
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const noexcept {
+ return __first_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() noexcept {
+ return __begin_;
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const noexcept {
+ return __begin_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __begin_ + __size_;
+#else
+ return __end_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __begin_ + __size_;
+#else
+ return __end_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __size_;
+#else
+ return static_cast<size_type>(__end_ - __begin_);
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __size_ == 0;
+#else
+ return __begin_ == __end_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __cap_;
+#else
+ return static_cast<size_type>(__cap_ - __first_);
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __first_ + __cap_;
+#else
+ return __cap_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __first_ + __cap_;
+#else
+ return __cap_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __size_ -= __new_begin - __begin_;
+#else
+ // TODO: explain why there isn't a pointer-based analogue
+#endif
+
+ __begin_ = __new_begin;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const noexcept {
+ return static_cast<size_type>(__begin_ - __first_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) noexcept {
+ _LIBCPP_ASSERT(__first_ <= __new_end, "__new_end cannot precede __first_");
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __size_ += __new_end - end();
+#else
+ __end_ = __new_end;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __size_ = __new_size;
+#else
+ __end_ = __begin_ + __new_size;
+#endif
+ }
- __split_buffer(const __split_buffer&) = delete;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __cap_ = __new_capacity;
+#else
+ __cap_ = __first_ + __new_capacity;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ // `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
+ // the __front_spare from the count.
+ return __cap_ - __size_ - __front_spare();
+#else
+ return static_cast<size_type>(__cap_ - __end_);
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __begin_[__size_ - 1];
+#else
+ return *(__end_ - 1);
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __begin_[__size_ - 1];
+#else
+ return *(__end_ - 1);
+#endif
+ }
+
+ template<class _Data2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) noexcept {
+ std::swap(__first_, __other.__first_);
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__cap_, __other.__cap_);
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ std::swap(__size_, __other.__size_);
+#else
+ std::swap(__end_, __other.__end_);
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__data& __other) noexcept {
+ __swap_without_allocator(__other);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const noexcept {
+ if (__first_ == nullptr) {
+ if (__begin_ != nullptr) {
+ return false;
+ }
+
+ if (!empty()) {
+ return false;
+ }
+
+ if (capacity() != 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ if (__begin_ < __first_) {
+ return false;
+ }
+
+ if (capacity() < size()) {
+ return false;
+ }
+
+ if (end() < __begin_) {
+ return false;
+ }
+
+ return true;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const noexcept {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ return __size_ == __cap_;
+#else
+ return __end_ == __cap_;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() noexcept {
+ __first_ = nullptr;
+ __begin_ = nullptr;
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __size_ = 0;
+ __cap_ = 0;
+#else
+ __end_ = nullptr;
+ __cap_ = nullptr;
+#endif
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__data const& __other)
+ noexcept(is_nothrow_copy_assignable<pointer>::value)
+ {
+ __first_ = __other.__first_;
+ __begin_ = __other.__begin_;
+ __cap_ = __other.__cap_;
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __size_ = __other.__size_;
+#else
+ __end_ = __other.__end_;
+#endif
+ }
+ };
+
+ __data __data_;
+
+ __split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr) {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_{}
+ {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_(__a)
+ {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_(__a)
+ {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
@@ -111,36 +350,22 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __data_.begin(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __data_.begin(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __data_.end(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __data_.end(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __end_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __end_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__data_.__begin_); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const { return __data_.size(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __data_.empty(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__begin_); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { return __data_.capacity(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const {
- return static_cast<size_type>(__end_ - __begin_);
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__data_.__begin_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__data_.__begin_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {
- return static_cast<size_type>(__cap_ - __first_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {
- return static_cast<size_type>(__begin_ - __first_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {
- return static_cast<size_type>(__cap_ - __end_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__begin_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return __data_.back(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return __data_.back(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -149,8 +374,8 @@ public:
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__begin_ + 1); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__end_ - 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__data_.begin() + 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__data_.end() - 1); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
@@ -185,66 +410,52 @@ public:
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
-
private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __alloc_ = std::move(__c.__alloc_);
+ __data_.__alloc_ = std::move(__c.__data_.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {}
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20
- _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT
- : __pos_(*__p),
- __end_(*__p + __n),
- __dest_(__p) {}
+ _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(__split_buffer* __parent, pointer __p, size_type __n) noexcept
+ : __pos_(__p),
+ __end_(__p + __n),
+ __parent_(__parent) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { *__dest_ = __pos_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
+ __parent_->__data_.__update_sentinel(__pos_);
+ }
pointer __pos_;
const pointer __end_;
private:
- pointer* __dest_;
+ __split_buffer* __parent_;
};
};
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants() const {
- if (__first_ == nullptr) {
- if (__begin_ != nullptr)
- return false;
- if (__end_ != nullptr)
- return false;
- if (__cap_ != nullptr)
- return false;
- } else {
- if (__begin_ < __first_)
- return false;
- if (__end_ < __begin_)
- return false;
- if (__cap_ < __end_)
- return false;
- }
- return true;
+ return __data_.__invariants();
}
-// Default constructs __n objects starting at __end_
+// Default constructs __n objects starting at `__begin_ + size()`
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
// Postcondition: size() == size() + __n
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) {
- _ConstructTransaction __tx(std::addressof(this->__end_), __n);
+ _ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
- __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_));
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_));
}
}
-// Copy constructs __n objects starting at __end_ from __x
+// Copy constructs __n objects starting at `__begin_ + size()` from __x
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -253,30 +464,35 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
- _ConstructTransaction __tx(std::addressof(this->__end_), __n);
+ _ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
- __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), __x);
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), __x);
}
}
-template <class _Tp, class _Allocator>
-template <class _Iterator, class _Sentinel>
+template<class _Tp, class _Allocator>
+template<class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
- __alloc_rr& __a = __alloc_;
+ __alloc_rr& __a = __data_.__alloc_;
for (; __first != __last; ++__first) {
- if (__end_ == __cap_) {
- size_type __old_cap = __cap_ - __first_;
+ if (__data_.__back_spare() == 0) {
+ size_type __old_cap = __data_.capacity();
size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
__split_buffer __buf(__new_cap, 0, __a);
- for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_)
- __alloc_traits::construct(__buf.__alloc_, std::__to_address(__buf.__end_), std::move(*__p));
+ pointer __buf_end = __buf.__data_.end();
+ pointer __end = __data_.end();
+ for (pointer __p = __data_.__begin_; __p != __end; ++__p, (void)++__buf_end)
+ __alloc_traits::construct(__buf.__data_.__alloc_, std::__to_address(__buf_end), std::move(*__p));
+ __buf.__data_.__update_sentinel(__buf_end);
swap(__buf);
}
- __alloc_traits::construct(__a, std::__to_address(this->__end_), *__first);
- ++this->__end_;
+
+ __alloc_traits::construct(__a, std::__to_address(__data_.end()), *__first);
+ __data_.__update_sentinel(size() + 1);
}
}
+
template <class _Tp, class _Allocator>
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
@@ -288,92 +504,82 @@ template <class _Tp, class _Allocator>
template <class _ForwardIterator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
- _ConstructTransaction __tx(std::addressof(this->__end_), __n);
+ _ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) {
- __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), *__first);
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), *__first);
}
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) {
- while (__begin_ != __new_begin)
- __alloc_traits::destroy(__alloc_, std::__to_address(__begin_++));
+ pointer __begin = __data_.__begin_;
+ while (__begin != __new_begin)
+ __alloc_traits::destroy(__data_.__alloc_, std::__to_address(__begin++));
+ __data_.__update_begin(__begin);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) {
- __begin_ = __new_begin;
+ __data_.__update_begin(__new_begin);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
- while (__new_last != __end_)
- __alloc_traits::destroy(__alloc_, std::__to_address(--__end_));
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
-__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT {
- __end_ = __new_last;
+ pointer __end = __data_.end();
+ while (__new_last != __end)
+ __alloc_traits::destroy(__data_.__alloc_, std::__to_address(--__end));
+ __data_.__update_sentinel(__end);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
- : __cap_(nullptr), __alloc_(__a) {
- if (__cap == 0) {
- __first_ = nullptr;
- } else {
- auto __allocation = std::__allocate_at_least(__alloc_, __cap);
- __first_ = __allocation.ptr;
- __cap = __allocation.count;
+ : __data_(__a) {
+ _LIBCPP_ASSERT(__cap >= __start, "can't have a start point outside the capacity");
+ if (__cap > 0) {
+ auto __allocation = std::__allocate_at_least(__data_.__alloc_, __cap);
+ __data_.__first_ = __allocation.ptr;
+ __cap = __allocation.count;
}
- __begin_ = __end_ = __first_ + __start;
- __cap_ = __first_ + __cap;
+
+ __data_.__begin_ = __data_.__first_ + __start;
+ __data_.__update_sentinel(__data_.__begin_);
+ __data_.__update_capacity(__cap);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() {
clear();
- if (__first_)
- __alloc_traits::deallocate(__alloc_, __first_, capacity());
+ if (__data_.__first_)
+ __alloc_traits::deallocate(__data_.__alloc_, __data_.__first_, capacity());
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __first_(std::move(__c.__first_)),
- __begin_(std::move(__c.__begin_)),
- __end_(std::move(__c.__end_)),
- __cap_(std::move(__c.__cap_)),
- __alloc_(std::move(__c.__alloc_)) {
- __c.__first_ = nullptr;
- __c.__begin_ = nullptr;
- __c.__end_ = nullptr;
- __c.__cap_ = nullptr;
+ : __data_(std::move(__c.__data_)) {
+ __c.__data_.__reset();
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
- : __cap_(nullptr), __alloc_(__a) {
- if (__a == __c.__alloc_) {
- __first_ = __c.__first_;
- __begin_ = __c.__begin_;
- __end_ = __c.__end_;
- __cap_ = __c.__cap_;
- __c.__first_ = nullptr;
- __c.__begin_ = nullptr;
- __c.__end_ = nullptr;
- __c.__cap_ = nullptr;
+ : __data_(__a) {
+ if (__a == __c.__data_.__alloc_) {
+ __data_.__first_ = __c.__data_.__first_;
+ __data_.__begin_ = __c.__data_.__begin_;
+ __data_.__update_sentinel(__c.__data_.end());
+ __data_.__update_capacity(__c.__data_.capacity());
+ __c.__data_.__reset();
} else {
- auto __allocation = std::__allocate_at_least(__alloc_, __c.size());
- __first_ = __allocation.ptr;
- __begin_ = __end_ = __first_;
- __cap_ = __first_ + __allocation.count;
+ auto __allocation = std::__allocate_at_least(__data_.__alloc_, __c.size());
+ __data_.__first_ = __allocation.ptr;
+ __data_.__begin_ = __data_.__first_;
+ __data_.__update_sentinel(__data_.__first_);
+ __data_.__update_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
}
@@ -387,23 +593,16 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
!__alloc_traits::propagate_on_container_move_assignment::value) {
clear();
shrink_to_fit();
- __first_ = __c.__first_;
- __begin_ = __c.__begin_;
- __end_ = __c.__end_;
- __cap_ = __c.__cap_;
+ __data_.__copy_without_alloc(__c.__data_);
__move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
- __c.__first_ = __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr;
+ __c.__data_.__reset();
return *this;
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
- std::swap(__first_, __x.__first_);
- std::swap(__begin_, __x.__begin_);
- std::swap(__end_, __x.__end_);
- std::swap(__cap_, __x.__cap_);
- std::__swap_allocator(__alloc_, __x.__alloc_);
+ __data_.swap(__x.__data_);
}
template <class _Tp, class _Allocator>
@@ -412,14 +611,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc_);
+ __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __data_.__alloc_);
if (__t.capacity() < capacity()) {
- __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
- __t.__end_ = __t.__begin_ + (__end_ - __begin_);
- std::swap(__first_, __t.__first_);
- std::swap(__begin_, __t.__begin_);
- std::swap(__end_, __t.__end_);
- std::swap(__cap_, __t.__cap_);
+ __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__data_.end()));
+ __t.__data_.__update_sentinel(__data_.size());
+ __data_.__swap_without_allocator(__t.__data_);
}
#if _LIBCPP_HAS_EXCEPTIONS
} catch (...) {
@@ -431,52 +627,61 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) {
- if (__begin_ == __first_) {
- if (__end_ < __cap_) {
- difference_type __d = __cap_ - __end_;
+ if (__data_.__begin_ == __data_.__first_) {
+ pointer __end = __data_.end();
+ if (__data_.__front_spare() != 0) {
+ difference_type __d = __data_.__back_spare();
__d = (__d + 1) / 2;
- __begin_ = std::move_backward(__begin_, __end_, __end_ + __d);
- __end_ += __d;
+ __data_.__begin_ = std::move_backward(__data_.__begin_, __end, __end + __d);
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ // TODO: explain why there isn't a size-based analogue
+#else
+ __data_.__end_ += __d;
+#endif
} else {
- size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1);
- __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
- std::swap(__first_, __t.__first_);
- std::swap(__begin_, __t.__begin_);
- std::swap(__end_, __t.__end_);
- std::swap(__cap_, __t.__cap_);
+ size_type __c = std::max<size_type>(2 * capacity(), 1);
+ __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __data_.__alloc_);
+ __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__end));
+ __data_.__swap_without_allocator(__t.__data_);
}
}
- __alloc_traits::construct(__alloc_, std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...);
- --__begin_;
+
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__data_.__begin_ - 1), std::forward<_Args>(__args)...);
+ --__data_.__begin_;
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __data_.__update_sentinel(__data_.end() + 1);
+#else
+ // TODO: explain why there isn't a pointer-based analogue
+#endif
}
-template <class _Tp, class _Allocator>
-template <class... _Args>
+template<class _Tp, class _Allocator>
+template<class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
- if (__end_ == __cap_) {
- if (__begin_ > __first_) {
- difference_type __d = __begin_ - __first_;
+ pointer __end = __data_.end();
+ if (__data_.__back_spare() == 0) {
+ if (__data_.__begin_ > __data_.__first_) {
+ difference_type __d = __data_.__begin_ - __data_.__first_;
__d = (__d + 1) / 2;
- __end_ = std::move(__begin_, __end_, __begin_ - __d);
- __begin_ -= __d;
+ __end = std::move(__data_.__begin_, __end, __data_.__begin_ - __d);
+ __data_.__begin_ -= __d;
+ __data_.__update_sentinel(__end);
} else {
- size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1);
- __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
- std::swap(__first_, __t.__first_);
- std::swap(__begin_, __t.__begin_);
- std::swap(__end_, __t.__end_);
- std::swap(__cap_, __t.__cap_);
+ size_type __c = std::max<size_type>(2 * capacity(), 1);
+ __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __data_.__alloc_);
+ __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__end));
+ __data_.__swap_without_allocator(__t.__data_);
}
}
- __alloc_traits::construct(__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...);
- ++__end_;
+
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __data_.__update_sentinel(++__end);
}
-template <class _Tp, class _Allocator>
+template<class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
-swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
+swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
+{
__x.swap(__y);
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 4e0d76fbbe3de..0aec0e21cdece 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -841,15 +841,16 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
__annotate_delete();
- auto __new_begin = __v.__begin_ - (__end_ - __begin_);
+ 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));
- __v.__begin_ = __new_begin;
+ __v.__data_.__begin_ = __new_begin;
__end_ = __begin_; // All the objects have been destroyed by relocating them.
- std::swap(this->__begin_, __v.__begin_);
- std::swap(this->__end_, __v.__end_);
- std::swap(this->__cap_, __v.__cap_);
- __v.__first_ = __v.__begin_;
+
+ std::swap(this->__begin_, __v.__data_.__begin_);
+ std::swap(this->__end_, __v.__data_.__end_);
+ std::swap(this->__cap_, __v.__data_.__cap_);
+ __v.__data_.__first_ = __v.begin();
__annotate_new(size());
}
@@ -861,25 +862,25 @@ 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) {
__annotate_delete();
- pointer __ret = __v.__begin_;
+ pointer __ret = __v.begin();
// Relocate [__p, __end_) first to avoid having a hole in [__begin_, __end_)
// in case something in [__begin_, __p) throws.
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.__end_));
- __v.__end_ += (__end_ - __p);
+ this->__alloc_, std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.end()));
+ auto __relocated_so_far = __end_ - __p;
+ __v.__data_.__update_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_);
+ auto __new_begin = __v.begin() - (__p - __begin_);
std::__uninitialized_allocator_relocate(
this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__begin_ = __new_begin;
+ __v.__data_.__begin_ = __new_begin;
__end_ = __begin_; // All the objects have been destroyed by relocating them.
-
- std::swap(this->__begin_, __v.__begin_);
- std::swap(this->__end_, __v.__end_);
- std::swap(this->__cap_, __v.__cap_);
- __v.__first_ = __v.__begin_;
+ std::swap(this->__begin_, __v.__data_.__begin_);
+ std::swap(this->__end_, __v.__data_.__end_);
+ std::swap(this->__cap_, __v.__data_.__cap_);
+ __v.__data_.__first_ = __v.begin();
__annotate_new(size());
return __ret;
}
@@ -1127,8 +1128,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
- __alloc_traits::construct(this->__alloc_, std::__to_address(__v.__end_), std::forward<_Args>(__args)...);
- __v.__end_++;
+ pointer __end = __v.end();
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __v.__data_.__update_sentinel(++__end);
__swap_out_circular_buffer(__v);
return this->__end_;
}
@@ -1303,14 +1305,14 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__split_buffer<value_type, allocator_type&> __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(this->__end_), std::__to_address(__merged.__end_));
+ __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.__end_ += this->__end_ - __old_last;
+ __merged.__data_.__update_sentinel(__merged.end() + (this->__end_ - __old_last));
this->__end_ = __old_last;
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__v.__begin_), std::__to_address(__v.__end_), std::__to_address(__merged.__end_));
- __merged.__end_ += __v.size();
- __v.__end_ = __v.__begin_;
+ __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __merged.__data_.__update_sentinel(__merged.size() + __v.size());
+ __v.__data_.__update_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
}
return __make_iter(__p);
diff --git a/libcxx/include/deque b/libcxx/include/deque
index d8645d06ae59e..2545622f53740 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1240,7 +1240,7 @@ private:
shrink_to_fit();
}
__alloc() = __c.__alloc();
- __map_.__alloc_ = __c.__map_.__alloc_;
+ __map_.__data_.__alloc_ = __c.__map_.__data_.__alloc_;
}
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const deque&, false_type) {}
@@ -1319,7 +1319,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c)
: __map_(__pointer_allocator(__alloc_traits::select_on_container_copy_construction(__c.__alloc()))),
__start_(0),
__size_(0),
- __alloc_(__map_.__alloc_) {
+ __alloc_(__map_.__data_.__alloc_) {
__annotate_new(0);
__append(__c.begin(), __c.end());
}
@@ -2058,7 +2058,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
- if (__map_.__front_spare() > 0)
+ if (__map_.__data_.__front_spare() > 0)
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
else {
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
@@ -2072,7 +2072,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
// Else need to allocate 1 buffer, *and* we need to reallocate __map_.
else {
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), 1), 0, __map_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), 1), 0, __map_.__data_.__alloc_);
typedef __allocator_destructor<_Allocator> _Dp;
unique_ptr<pointer, _Dp> __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size));
@@ -2081,10 +2081,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i)
__buf.emplace_back(*__i);
- std::swap(__map_.__first_, __buf.__first_);
- std::swap(__map_.__begin_, __buf.__begin_);
- std::swap(__map_.__end_, __buf.__end_);
- std::swap(__map_.__cap_, __buf.__cap_);
+ __map_.__data_.__swap_without_allocator(__buf.__data_);
__start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size;
}
__annotate_whole_block(0, __asan_poison);
@@ -2115,7 +2112,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
for (; __nb > 0; --__nb, __start_ += __block_size - (__map_.size() == 1)) {
- if (__map_.__front_spare() == 0)
+ if (__map_.__data_.__front_spare() == 0)
break;
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
__annotate_whole_block(0, __asan_poison);
@@ -2135,7 +2132,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
else {
size_type __ds = (__nb + __back_capacity) * __block_size - __map_.empty();
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__data_.__alloc_);
# if _LIBCPP_HAS_EXCEPTIONS
try {
# endif // _LIBCPP_HAS_EXCEPTIONS
@@ -2158,10 +2155,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
}
for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i)
__buf.emplace_back(*__i);
- std::swap(__map_.__first_, __buf.__first_);
- std::swap(__map_.__begin_, __buf.__begin_);
- std::swap(__map_.__end_, __buf.__end_);
- std::swap(__map_.__cap_, __buf.__cap_);
+ __map_.__data_.__swap_without_allocator(__buf.__data_);
__start_ += __ds;
}
}
@@ -2181,7 +2175,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around
// until it is allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
- if (__map_.__back_spare() != 0)
+ if (__map_.__data_.__back_spare() != 0)
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
else {
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
@@ -2195,7 +2189,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
// Else need to allocate 1 buffer, *and* we need to reallocate __map_.
else {
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), 1), __map_.size(), __map_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), 1), __map_.size(), __map_.__data_.__alloc_);
typedef __allocator_destructor<_Allocator> _Dp;
unique_ptr<pointer, _Dp> __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size));
@@ -2204,10 +2198,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
for (__map_pointer __i = __map_.end(); __i != __map_.begin();)
__buf.emplace_front(*--__i);
- std::swap(__map_.__first_, __buf.__first_);
- std::swap(__map_.__begin_, __buf.__begin_);
- std::swap(__map_.__end_, __buf.__end_);
- std::swap(__map_.__cap_, __buf.__cap_);
+ __map_.__data_.__swap_without_allocator(__buf.__data_);
__annotate_whole_block(__map_.size() - 1, __asan_poison);
}
}
@@ -2237,7 +2228,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
for (; __nb > 0; --__nb) {
- if (__map_.__back_spare() == 0)
+ if (__map_.__data_.__back_spare() == 0)
break;
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
__annotate_whole_block(__map_.size() - 1, __asan_poison);
@@ -2260,7 +2251,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
__split_buffer<pointer, __pointer_allocator&> __buf(
std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()),
__map_.size() - __front_capacity,
- __map_.__alloc_);
+ __map_.__data_.__alloc_);
# if _LIBCPP_HAS_EXCEPTIONS
try {
# endif // _LIBCPP_HAS_EXCEPTIONS
@@ -2283,10 +2274,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
}
for (__map_pointer __i = __map_.end(); __i != __map_.begin();)
__buf.emplace_front(*--__i);
- std::swap(__map_.__first_, __buf.__first_);
- std::swap(__map_.__begin_, __buf.__begin_);
- std::swap(__map_.__end_, __buf.__end_);
- std::swap(__map_.__cap_, __buf.__cap_);
+ __map_.__data_.__swap_without_allocator(__buf.__data_);
__start_ -= __ds;
}
}
>From 13551cb4f2fa16c6322b9acb67e5b201c6f70af3 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 May 2025 18:31:30 +0000
Subject: [PATCH 02/28] fixes CI issues
---
libcxx/include/__split_buffer | 54 ++++++++++++++---------------
libcxx/utils/gdb/libcxx/printers.py | 2 +-
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 9710dfec774f7..0cd1a0e360c59 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -97,21 +97,21 @@ public:
: __alloc_(__alloc)
{}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT {
return __first_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT {
return __first_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT {
return __begin_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT {
return __begin_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __begin_ + __size_;
#else
@@ -119,7 +119,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __begin_ + __size_;
#else
@@ -127,7 +127,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __size_;
#else
@@ -135,7 +135,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __size_ == 0;
#else
@@ -143,7 +143,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __cap_;
#else
@@ -151,7 +151,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __first_ + __cap_;
#else
@@ -159,7 +159,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __first_ + __cap_;
#else
@@ -167,7 +167,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
__size_ -= __new_begin - __begin_;
#else
@@ -177,11 +177,11 @@ public:
__begin_ = __new_begin;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
return static_cast<size_type>(__begin_ - __first_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
_LIBCPP_ASSERT(__first_ <= __new_end, "__new_end cannot precede __first_");
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
__size_ += __new_end - end();
@@ -190,7 +190,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
__size_ = __new_size;
#else
@@ -198,7 +198,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
__cap_ = __new_capacity;
#else
@@ -206,7 +206,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
// `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
// the __front_spare from the count.
@@ -216,7 +216,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __begin_[__size_ - 1];
#else
@@ -224,7 +224,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __begin_[__size_ - 1];
#else
@@ -233,7 +233,7 @@ public:
}
template<class _Data2>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
std::swap(__first_, __other.__first_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
@@ -244,12 +244,12 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__data& __other) noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__data& __other) _NOEXCEPT {
__swap_without_allocator(__other);
std::__swap_allocator(__alloc_, __other.__alloc_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT {
if (__first_ == nullptr) {
if (__begin_ != nullptr) {
return false;
@@ -281,7 +281,7 @@ public:
return true;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
return __size_ == __cap_;
#else
@@ -289,7 +289,7 @@ public:
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() noexcept {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
__first_ = nullptr;
__begin_ = nullptr;
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -302,7 +302,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__data const& __other)
- noexcept(is_nothrow_copy_assignable<pointer>::value)
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
{
__first_ = __other.__first_;
__begin_ = __other.__begin_;
@@ -322,7 +322,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_{}
+ : __data_()
{}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
@@ -420,7 +420,7 @@ private:
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20
- _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(__split_buffer* __parent, pointer __p, size_type __n) noexcept
+ _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(__split_buffer* __parent, pointer __p, size_type __n) _NOEXCEPT
: __pos_(__p),
__end_(__p + __n),
__parent_(__parent) {}
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 31c27a1959cb2..8194f584ea137 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -426,7 +426,7 @@ class StdDequePrinter(object):
def __init__(self, val):
self.val = val
self.size = int(val["__size_"])
- self.start_ptr = self.val["__map_"]["__begin_"]
+ self.start_ptr = self.val["__map_"]["__data_"]["__begin_"]
self.first_block_start_index = int(self.val["__start_"])
self.node_type = self.start_ptr.type
self.block_size = self._calculate_block_size(val.type.template_argument(0))
>From 6d3ec2b72a51d032fa81f52e29066f274b31fc5b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 27 May 2025 17:51:55 +0000
Subject: [PATCH 03/28] applies suggestions
---
libcxx/include/__split_buffer | 86 ++++++++++++-----------------------
1 file changed, 29 insertions(+), 57 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 0cd1a0e360c59..e9bad689992c0 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -83,12 +83,13 @@ public:
struct __data {
pointer __first_ = nullptr;
pointer __begin_ = nullptr;
-#ifndef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ allocator_type __alloc_;
+#else
pointer __end_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-#else
- size_type __size_ = 0;
- _LIBCPP_COMPRESSED_PAIR(size_type, __cap_ = 0, allocator_type, __alloc_);
#endif
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __data() = default;
@@ -97,13 +98,6 @@ public:
: __alloc_(__alloc)
{}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT {
- return __first_;
- }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT {
- return __first_;
- }
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT {
return __begin_;
}
@@ -112,7 +106,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __begin_ + __size_;
#else
return __end_;
@@ -120,7 +114,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __begin_ + __size_;
#else
return __end_;
@@ -128,7 +122,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __size_;
#else
return static_cast<size_type>(__end_ - __begin_);
@@ -136,7 +130,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __size_ == 0;
#else
return __begin_ == __end_;
@@ -144,31 +138,15 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __cap_;
#else
return static_cast<size_type>(__cap_ - __first_);
#endif
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- return __first_ + __cap_;
-#else
- return __cap_;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __capacity_as_pointer() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- return __first_ + __cap_;
-#else
- return __cap_;
-#endif
- }
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__size_ -= __new_begin - __begin_;
#else
// TODO: explain why there isn't a pointer-based analogue
@@ -183,7 +161,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
_LIBCPP_ASSERT(__first_ <= __new_end, "__new_end cannot precede __first_");
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__size_ += __new_end - end();
#else
__end_ = __new_end;
@@ -191,7 +169,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__size_ = __new_size;
#else
__end_ = __begin_ + __new_size;
@@ -199,7 +177,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__cap_ = __new_capacity;
#else
__cap_ = __first_ + __new_capacity;
@@ -207,7 +185,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
// `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
// the __front_spare from the count.
return __cap_ - __size_ - __front_spare();
@@ -217,7 +195,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __begin_[__size_ - 1];
#else
return *(__end_ - 1);
@@ -225,7 +203,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __begin_[__size_ - 1];
#else
return *(__end_ - 1);
@@ -237,7 +215,7 @@ public:
std::swap(__first_, __other.__first_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
std::swap(__size_, __other.__size_);
#else
std::swap(__end_, __other.__end_);
@@ -251,38 +229,32 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT {
if (__first_ == nullptr) {
- if (__begin_ != nullptr) {
+ if (__begin_ != nullptr)
return false;
- }
- if (!empty()) {
+ if (!empty())
return false;
- }
- if (capacity() != 0) {
+ if (capacity() != 0)
return false;
- }
return true;
}
- if (__begin_ < __first_) {
+ if (__begin_ < __first_)
return false;
- }
- if (capacity() < size()) {
+ if (capacity() < size())
return false;
- }
- if (end() < __begin_) {
+ if (end() < __begin_)
return false;
- }
return true;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
return __size_ == __cap_;
#else
return __end_ == __cap_;
@@ -292,7 +264,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
__first_ = nullptr;
__begin_ = nullptr;
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__size_ = 0;
__cap_ = 0;
#else
@@ -307,7 +279,7 @@ public:
__first_ = __other.__first_;
__begin_ = __other.__begin_;
__cap_ = __other.__cap_;
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__size_ = __other.__size_;
#else
__end_ = __other.__end_;
@@ -633,7 +605,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
difference_type __d = __data_.__back_spare();
__d = (__d + 1) / 2;
__data_.__begin_ = std::move_backward(__data_.__begin_, __end, __end + __d);
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
// TODO: explain why there isn't a size-based analogue
#else
__data_.__end_ += __d;
@@ -648,7 +620,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
__alloc_traits::construct(__data_.__alloc_, std::__to_address(__data_.__begin_ - 1), std::forward<_Args>(__args)...);
--__data_.__begin_;
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
__data_.__update_sentinel(__data_.end() + 1);
#else
// TODO: explain why there isn't a pointer-based analogue
>From 7084c96db07cb60f2e63ca973730f85f09870d00 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 29 May 2025 21:57:15 +0000
Subject: [PATCH 04/28] updates formatting
---
libcxx/include/__split_buffer | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index e9bad689992c0..1e7d33fd433da 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -239,18 +239,18 @@ public:
return false;
return true;
- }
-
- if (__begin_ < __first_)
- return false;
+ } else {
+ if (__begin_ < __first_)
+ return false;
- if (capacity() < size())
- return false;
+ if (capacity() < size())
+ return false;
- if (end() < __begin_)
- return false;
+ if (end() < __begin_)
+ return false;
- return true;
+ return true;
+ }
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
>From af7c901f6a457cef23677cdc82ce6d3950a4c00b Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Tue, 3 Jun 2025 19:39:38 +0000
Subject: [PATCH 05/28] changes deque's pretty-printer to work with new
__split_buffer
---
lldb/examples/synthetic/libcxx.py | 54 ++++++++++++++++++++++++-------
1 file changed, 42 insertions(+), 12 deletions(-)
diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py
index 5abeb3061f4f5..521bd06af5b3f 100644
--- a/lldb/examples/synthetic/libcxx.py
+++ b/lldb/examples/synthetic/libcxx.py
@@ -1,3 +1,6 @@
+from enum import Enum
+from sys import stderr
+import sys
import lldb
import lldb.formatters.Logger
@@ -74,6 +77,40 @@ def stdstring_SummaryProvider(valobj, dict):
return '"' + strval + '"'
+def get_buffer_data(parent):
+ map_valobj = parent.valobj.GetChildMemberWithName("__map_")
+ map_data = map_valobj.GetChildMemberWithName("__data_")
+ if map_data.IsValid():
+ return map_data
+
+ return map_valobj
+
+
+def get_buffer_end(buffer, begin):
+ map_end = buffer.GetChildMemberWithName("__end_")
+ if map_end.IsValid():
+ return map_end.GetValueAsUnsigned(0)
+ map_size = buffer.GetChildMemberWithName("__size_").GetValueAsUnsigned(0)
+ return begin + map_size
+
+
+def get_buffer_endcap(parent, buffer, begin, has_compressed_pair_layout, is_size_based):
+ if has_compressed_pair_layout:
+ map_endcap = parent._get_value_of_compressed_pair(
+ buffer.GetChildMemberWithName("__end_cap_")
+ )
+ else:
+ map_endcap = buffer.GetChildMemberWithName("__cap_")
+ if not map_endcap.IsValid():
+ map_endcap = buffer.GetChildMemberWithName("__end_cap_")
+ map_endcap = map_endcap.GetValueAsUnsigned(0)
+
+ if is_size_based:
+ return begin + map_endcap
+
+ return map_endcap
+
+
class stdvector_SynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
@@ -755,23 +792,16 @@ def update(self):
if self.block_size < 0:
logger.write("block_size < 0")
return
- map_ = self.valobj.GetChildMemberWithName("__map_")
start = self.valobj.GetChildMemberWithName("__start_").GetValueAsUnsigned(0)
+
+ map_ = get_buffer_data(self)
+ is_size_based = map_.GetChildMemberWithName("__size_").IsValid()
first = map_.GetChildMemberWithName("__first_")
map_first = first.GetValueAsUnsigned(0)
self.map_begin = map_.GetChildMemberWithName("__begin_")
map_begin = self.map_begin.GetValueAsUnsigned(0)
- map_end = map_.GetChildMemberWithName("__end_").GetValueAsUnsigned(0)
-
- if has_compressed_pair_layout:
- map_endcap = self._get_value_of_compressed_pair(
- map_.GetChildMemberWithName("__end_cap_")
- )
- else:
- map_endcap = map_.GetChildMemberWithName("__cap_")
- if not map_endcap.IsValid():
- map_endcap = map_.GetChildMemberWithName("__end_cap_")
- map_endcap = map_endcap.GetValueAsUnsigned(0)
+ map_end = get_buffer_end(map_, map_begin)
+ map_endcap = get_buffer_endcap(self, map_, map_begin, has_compressed_pair_layout, is_size_based)
# check consistency
if not map_first <= map_begin <= map_end <= map_endcap:
>From 66282c1c0c67304abf75a1eef18f62d6faf0fe64 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 2 Jul 2025 22:41:10 +0000
Subject: [PATCH 06/28] responds to feedback
---
libcxx/include/__split_buffer | 567 +++++++++++++++++--------------
libcxx/include/__vector/vector.h | 2 +-
2 files changed, 317 insertions(+), 252 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1e7d33fd433da..ef5efea489265 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -80,214 +80,8 @@ public:
__split_buffer,
void>;
- struct __data {
- pointer __first_ = nullptr;
- pointer __begin_ = nullptr;
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- size_type __size_ = 0;
- size_type __cap_ = 0;
- allocator_type __alloc_;
-#else
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-#endif
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __data() = default;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __data(const allocator_type& __alloc)
- : __alloc_(__alloc)
- {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT {
- return __begin_;
- }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT {
- return __begin_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __begin_ + __size_;
-#else
- return __end_;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __begin_ + __size_;
-#else
- return __end_;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __size_;
-#else
- return static_cast<size_type>(__end_ - __begin_);
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __size_ == 0;
-#else
- return __begin_ == __end_;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __cap_;
-#else
- return static_cast<size_type>(__cap_ - __first_);
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __size_ -= __new_begin - __begin_;
-#else
- // TODO: explain why there isn't a pointer-based analogue
-#endif
-
- __begin_ = __new_begin;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
- _LIBCPP_ASSERT(__first_ <= __new_end, "__new_end cannot precede __first_");
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __size_ += __new_end - end();
-#else
- __end_ = __new_end;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __size_ = __new_size;
-#else
- __end_ = __begin_ + __new_size;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __cap_ = __new_capacity;
-#else
- __cap_ = __first_ + __new_capacity;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- // `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
- // the __front_spare from the count.
- return __cap_ - __size_ - __front_spare();
-#else
- return static_cast<size_type>(__cap_ - __end_);
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __begin_[__size_ - 1];
-#else
- return *(__end_ - 1);
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __begin_[__size_ - 1];
-#else
- return *(__end_ - 1);
-#endif
- }
-
- template<class _Data2>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
- std::swap(__first_, __other.__first_);
- std::swap(__begin_, __other.__begin_);
- std::swap(__cap_, __other.__cap_);
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- std::swap(__size_, __other.__size_);
-#else
- std::swap(__end_, __other.__end_);
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__data& __other) _NOEXCEPT {
- __swap_without_allocator(__other);
- std::__swap_allocator(__alloc_, __other.__alloc_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const _NOEXCEPT {
- if (__first_ == nullptr) {
- if (__begin_ != nullptr)
- return false;
-
- if (!empty())
- return false;
-
- if (capacity() != 0)
- return false;
-
- return true;
- } else {
- if (__begin_ < __first_)
- return false;
-
- if (capacity() < size())
- return false;
-
- if (end() < __begin_)
- return false;
-
- return true;
- }
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- return __size_ == __cap_;
-#else
- return __end_ == __cap_;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __first_ = nullptr;
- __begin_ = nullptr;
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __size_ = 0;
- __cap_ = 0;
-#else
- __end_ = nullptr;
- __cap_ = nullptr;
-#endif
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__data const& __other)
- _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
- {
- __first_ = __other.__first_;
- __begin_ = __other.__begin_;
- __cap_ = __other.__cap_;
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- __size_ = __other.__size_;
-#else
- __end_ = __other.__end_;
-#endif
- }
- };
-
- __data __data_;
+ struct __layout;
+ __layout __data_;
__split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;
@@ -327,14 +121,14 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __data_.end(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __data_.end(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__data_.__begin_); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__data_.begin()); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const { return __data_.size(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __data_.empty(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { return __data_.capacity(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__data_.__begin_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__data_.__begin_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__data_.begin(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__data_.begin(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return __data_.back(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return __data_.back(); }
@@ -381,7 +175,31 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__data_.first() == nullptr) {
+ if (__data_.begin() != nullptr)
+ return false;
+
+ if (!__data_.empty())
+ return false;
+
+ if (__data_.capacity() != 0)
+ return false;
+
+ return true;
+ } else {
+ if (__data_.begin() < __data_.first())
+ return false;
+
+ if (__data_.capacity() < __data_.size())
+ return false;
+
+ if (__data_.end() < __data_.begin())
+ return false;
+
+ return true;
+ }
+ }
private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
@@ -409,9 +227,247 @@ private:
};
};
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants() const {
- return __data_.__invariants();
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template<class _Tp, class _Allocatior>
+struct __split_buffer<_Tp, _Allocator>::__layout {
+// private:
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ _LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
+public:
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
+ : __alloc_(__alloc)
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return __size_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __size_ == 0;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _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;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ __size_ += __new_end - end();
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ __size_ = __new_size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ __cap_ = __new_capacity;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
+ // `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
+ // the __front_spare from the count.
+ return __cap_ - __size_ - __front_spare();
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ return __begin_[__size_ - 1];
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ return __begin_[__size_ - 1];
+ }
+
+ template<class _Data2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
+ std::swap(__first_, __other.__first_);
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__cap_, __other.__cap_);
+ std::swap(__size_, __other.__size_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__layout& __other) _NOEXCEPT {
+ __swap_without_allocator(__other);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
+ __first_ = nullptr;
+ __begin_ = nullptr;
+ __size_ = 0;
+ __cap_ = 0;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
+ {
+ __first_ = __other.__first_;
+ __begin_ = __other.__begin_;
+ __cap_ = __other.__cap_;
+ __size_ = __other.__size_;
+ }
+};
+#else
+template<class _Tp, class _Allocator>
+struct __split_buffer<_Tp, _Allocator>::__layout {
+// private:
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+public:
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
+ : __alloc_(__alloc)
+ {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
+ return __end_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
+ return __end_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __begin_ == __end_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __first_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ __end_ = __new_end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ __end_ = __begin_ + __new_size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ __cap_ = __first_ + __new_capacity;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __end_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ return *(__end_ - 1);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ return *(__end_ - 1);
+ }
+
+ template<class _OtherLayout>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_OtherLayout& __other) _NOEXCEPT {
+ std::swap(__first_, __other.__first_);
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__cap_, __other.__cap_);
+ std::swap(__end_, __other.__end_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__layout& __other) _NOEXCEPT {
+ __swap_without_allocator(__other);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
+ __first_ = nullptr;
+ __begin_ = nullptr;
+ __end_ = nullptr;
+ __cap_ = nullptr;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
+ {
+ __first_ = __other.__first_;
+ __begin_ = __other.__begin_;
+ __cap_ = __other.__cap_;
+ __end_ = __other.__end_;
+ }
+};
+#endif
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
+ __first_ = __new_first;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _NOEXCEPT {
+ __begin_ = __new_begin;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT -> pointer {
+ return __first_;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT -> const_pointer {
+ return __first_;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT -> pointer {
+ return __begin_;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT -> const_pointer {
+ return __begin_;
+}
+
+template<class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT -> size_type {
+ return static_cast<size_type>(__begin_ - __first_);
}
// Default constructs __n objects starting at `__begin_ + size()`
@@ -442,8 +498,8 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_referen
}
}
-template<class _Tp, class _Allocator>
-template<class _Iterator, class _Sentinel>
+template <class _Tp, class _Allocator>
+template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
__alloc_rr& __a = __data_.__alloc_;
@@ -454,9 +510,10 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __fi
__split_buffer __buf(__new_cap, 0, __a);
pointer __buf_end = __buf.__data_.end();
pointer __end = __data_.end();
- for (pointer __p = __data_.__begin_; __p != __end; ++__p, (void)++__buf_end)
+ for (pointer __p = __data_.begin(); __p != __end; ++__p) {
__alloc_traits::construct(__buf.__data_.__alloc_, std::__to_address(__buf_end), std::move(*__p));
- __buf.__data_.__update_sentinel(__buf_end);
+ __buf.__data_.__update_sentinel(++__buf_end);
+ }
swap(__buf);
}
@@ -485,7 +542,8 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator _
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) {
- pointer __begin = __data_.__begin_;
+ pointer __begin = __data_.begin();
+ // Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
while (__begin != __new_begin)
__alloc_traits::destroy(__data_.__alloc_, std::__to_address(__begin++));
__data_.__update_begin(__begin);
@@ -501,6 +559,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
pointer __end = __data_.end();
+ // Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
while (__new_last != __end)
__alloc_traits::destroy(__data_.__alloc_, std::__to_address(--__end));
__data_.__update_sentinel(__end);
@@ -510,23 +569,23 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
: __data_(__a) {
- _LIBCPP_ASSERT(__cap >= __start, "can't have a start point outside the capacity");
+ _LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
auto __allocation = std::__allocate_at_least(__data_.__alloc_, __cap);
- __data_.__first_ = __allocation.ptr;
- __cap = __allocation.count;
+ __data_.__update_first(__allocation.ptr);
+ __cap = __allocation.count;
}
- __data_.__begin_ = __data_.__first_ + __start;
- __data_.__update_sentinel(__data_.__begin_);
+ __data_.__update_begin(__data_.first() + __start);
+ __data_.__update_sentinel(__data_.begin());
__data_.__update_capacity(__cap);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() {
clear();
- if (__data_.__first_)
- __alloc_traits::deallocate(__data_.__alloc_, __data_.__first_, capacity());
+ if (__data_.first())
+ __alloc_traits::deallocate(__data_.__alloc_, __data_.first(), capacity());
}
template <class _Tp, class _Allocator>
@@ -541,16 +600,16 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __data_(__a) {
if (__a == __c.__data_.__alloc_) {
- __data_.__first_ = __c.__data_.__first_;
- __data_.__begin_ = __c.__data_.__begin_;
+ __data_.__update_first(__c.__data_.first());
+ __data_.__update_begin(__c.__data_.begin());
__data_.__update_sentinel(__c.__data_.end());
__data_.__update_capacity(__c.__data_.capacity());
__c.__data_.__reset();
} else {
auto __allocation = std::__allocate_at_least(__data_.__alloc_, __c.size());
- __data_.__first_ = __allocation.ptr;
- __data_.__begin_ = __data_.__first_;
- __data_.__update_sentinel(__data_.__first_);
+ __data_.__update_first(__allocation.ptr);
+ __data_.__update_begin(__data_.first());
+ __data_.__update_sentinel(__data_.first());
__data_.__update_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
@@ -585,7 +644,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
#endif // _LIBCPP_HAS_EXCEPTIONS
__split_buffer<value_type, __alloc_rr&> __t(size(), 0, __data_.__alloc_);
if (__t.capacity() < capacity()) {
- __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__data_.end()));
+ __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__data_.end()));
__t.__data_.__update_sentinel(__data_.size());
__data_.__swap_without_allocator(__t.__data_);
}
@@ -599,31 +658,37 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) {
- if (__data_.__begin_ == __data_.__first_) {
+ if (__data_.__front_spare() == 0) {
pointer __end = __data_.end();
- if (__data_.__front_spare() != 0) {
+ if (__data_.__back_spare() > 0) {
+ // The elements are pressed up against the front of the buffer: we need to move them back a
+ // little bit to make `emplace_front` have amortised O(1) complexity.
difference_type __d = __data_.__back_spare();
__d = (__d + 1) / 2;
- __data_.__begin_ = std::move_backward(__data_.__begin_, __end, __end + __d);
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
- // TODO: explain why there isn't a size-based analogue
-#else
- __data_.__end_ += __d;
+ __data_.__update_begin(std::move_backward(__data_.begin(), __end, __end + __d));
+
+ // `__data_.begin()` was moved further into the buffer, so we need to update the pointer-based
+ // layout's end with it. We don't need to do anything for the size-based layout here, because
+ // the number of elements hasn't changed yet.
+#ifndef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ __data_.__update_sentinel(__data_.size() + __d);
#endif
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __data_.__alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__end));
+ __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__end));
__data_.__swap_without_allocator(__t.__data_);
}
}
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__data_.__begin_ - 1), std::forward<_Args>(__args)...);
- --__data_.__begin_;
-#ifdef _LIBCPP_ABI_SIZE_BASED_CONTAINERS
+ __alloc_traits::construct(__data_.__alloc_, std::__to_address(__data_.begin() - 1), std::forward<_Args>(__args)...);
+ __data_.__update_begin(__data_.begin() - 1);
+
+ // Now that we've added an element to the front of the buffer, we need to update the size-based
+ // layout's size. We don't need to do anything for the pointer-based layout here, because the end
+ // pointer was never updated.
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
__data_.__update_sentinel(__data_.end() + 1);
-#else
- // TODO: explain why there isn't a pointer-based analogue
#endif
}
@@ -632,16 +697,16 @@ template<class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
pointer __end = __data_.end();
if (__data_.__back_spare() == 0) {
- if (__data_.__begin_ > __data_.__first_) {
- difference_type __d = __data_.__begin_ - __data_.__first_;
+ if (__data_.__front_spare() > 0) {
+ difference_type __d = __data_.__front_spare();
__d = (__d + 1) / 2;
- __end = std::move(__data_.__begin_, __end, __data_.__begin_ - __d);
- __data_.__begin_ -= __d;
+ __end = std::move(__data_.begin(), __end, __data_.begin() - __d);
+ __data_.__update_begin(__data_.begin() - __d);
__data_.__update_sentinel(__end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __data_.__alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__data_.__begin_), move_iterator<pointer>(__end));
+ __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__end));
__data_.__swap_without_allocator(__t.__data_);
}
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 0aec0e21cdece..7110df086e77b 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -850,7 +850,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
std::swap(this->__begin_, __v.__data_.__begin_);
std::swap(this->__end_, __v.__data_.__end_);
std::swap(this->__cap_, __v.__data_.__cap_);
- __v.__data_.__first_ = __v.begin();
+ __v.__data_.__update_first(__v.begin());
__annotate_new(size());
}
>From ad937469eef906d8fd48cd2c1de0b4e575a1c1c6 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 2 Jul 2025 22:49:04 +0000
Subject: [PATCH 07/28] runs clang-format properly
---
libcxx/include/__split_buffer | 170 +++++++++++++++-------------------
1 file changed, 77 insertions(+), 93 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index ef5efea489265..a529345180083 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -175,31 +175,32 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__data_.first() == nullptr) {
- if (__data_.begin() != nullptr)
- return false;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__data_.first() == nullptr) {
+ if (__data_.begin() != nullptr)
+ return false;
- if (!__data_.empty())
- return false;
+ if (!__data_.empty())
+ return false;
- if (__data_.capacity() != 0)
- return false;
+ if (__data_.capacity() != 0)
+ return false;
- return true;
- } else {
- if (__data_.begin() < __data_.first())
- return false;
+ return true;
+ } else {
+ if (__data_.begin() < __data_.first())
+ return false;
- if (__data_.capacity() < __data_.size())
- return false;
+ if (__data_.capacity() < __data_.size())
+ return false;
- if (__data_.end() < __data_.begin())
- return false;
+ if (__data_.end() < __data_.begin())
+ return false;
- return true;
- }
+ return true;
+ }
}
+
private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
@@ -228,45 +229,35 @@ private:
};
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template<class _Tp, class _Allocatior>
+template <class _Tp, class _Allocatior>
struct __split_buffer<_Tp, _Allocator>::__layout {
-// private:
- pointer __first_ = nullptr;
- pointer __begin_ = nullptr;
+ // private:
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
size_type __size_ = 0;
- size_type __cap_ = 0;
+ size_type __cap_ = 0;
_LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
+
public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
- : __alloc_(__alloc)
- {}
+ : __alloc_(__alloc) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
- return __begin_ + __size_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __begin_ + __size_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
- return __begin_ + __size_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __begin_ + __size_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __size_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __size_ == 0;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __cap_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT;
@@ -298,15 +289,13 @@ public:
return __cap_ - __size_ - __front_spare();
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- return __begin_[__size_ - 1];
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return __begin_[__size_ - 1]; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
return __begin_[__size_ - 1];
}
- template<class _Data2>
+ template <class _Data2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
std::swap(__first_, __other.__first_);
std::swap(__begin_, __other.__begin_);
@@ -322,54 +311,47 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
__first_ = nullptr;
__begin_ = nullptr;
- __size_ = 0;
- __cap_ = 0;
+ __size_ = 0;
+ __cap_ = 0;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
- _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
- {
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
__first_ = __other.__first_;
__begin_ = __other.__begin_;
- __cap_ = __other.__cap_;
- __size_ = __other.__size_;
+ __cap_ = __other.__cap_;
+ __size_ = __other.__size_;
}
};
#else
-template<class _Tp, class _Allocator>
+template <class _Tp, class _Allocator>
struct __split_buffer<_Tp, _Allocator>::__layout {
-// private:
+ // private:
pointer __first_ = nullptr;
pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
+ pointer __end_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+
public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
- : __alloc_(__alloc)
- {}
+ : __alloc_(__alloc) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT {
- return __end_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __end_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT {
- return __end_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __end_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
return static_cast<size_type>(__end_ - __begin_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __begin_ == __end_;
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __begin_ == __end_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
return static_cast<size_type>(__cap_ - __first_);
@@ -396,15 +378,11 @@ public:
return static_cast<size_type>(__cap_ - __end_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- return *(__end_ - 1);
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return *(__end_ - 1); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- return *(__end_ - 1);
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
- template<class _OtherLayout>
+ template <class _OtherLayout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_OtherLayout& __other) _NOEXCEPT {
std::swap(__first_, __other.__first_);
std::swap(__begin_, __other.__begin_);
@@ -420,53 +398,59 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
__first_ = nullptr;
__begin_ = nullptr;
- __end_ = nullptr;
- __cap_ = nullptr;
+ __end_ = nullptr;
+ __cap_ = nullptr;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
- _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value)
- {
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
__first_ = __other.__first_;
__begin_ = __other.__begin_;
- __cap_ = __other.__cap_;
- __end_ = __other.__end_;
+ __cap_ = __other.__cap_;
+ __end_ = __other.__end_;
}
};
#endif
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
- __first_ = __new_first;
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+_LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
+ __first_ = __new_first;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _NOEXCEPT {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+__split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _NOEXCEPT {
__begin_ = __new_begin;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT -> pointer {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT
+ -> pointer {
return __first_;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT -> const_pointer {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
+__split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT -> const_pointer {
return __first_;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT -> pointer {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT
+ -> pointer {
return __begin_;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT -> const_pointer {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
+__split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT -> const_pointer {
return __begin_;
}
-template<class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT -> size_type {
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
+__split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT -> size_type {
return static_cast<size_type>(__begin_ - __first_);
}
@@ -573,7 +557,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta
if (__cap > 0) {
auto __allocation = std::__allocate_at_least(__data_.__alloc_, __cap);
__data_.__update_first(__allocation.ptr);
- __cap = __allocation.count;
+ __cap = __allocation.count;
}
__data_.__update_begin(__data_.first() + __start);
>From 275da6ffe79dbcece797c752b013c59121dca1ea Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 2 Jul 2025 22:52:53 +0000
Subject: [PATCH 08/28] re-runs clang format on
88bc35049f774c8c3a5c35ff22470a0670ee3e9d
---
libcxx/include/__split_buffer | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index a529345180083..f453c3a1e0f2c 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -87,9 +87,8 @@ public:
__split_buffer& operator=(const __split_buffer&) = delete;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_()
- {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_() {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
@@ -212,9 +211,9 @@ private:
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20
_LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(__split_buffer* __parent, pointer __p, size_type __n) _NOEXCEPT
- : __pos_(__p),
- __end_(__p + __n),
- __parent_(__parent) {}
+ : __pos_(__p),
+ __end_(__p + __n),
+ __parent_(__parent) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
__parent_->__data_.__update_sentinel(__pos_);
>From 89daf490ff5073070b963f3ced5cf61ddc615ccc Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 7 Jul 2025 17:20:12 +0000
Subject: [PATCH 09/28] addresses CI issues
---
libcxx/include/__split_buffer | 45 ++++++++++++++++-------------------
1 file changed, 21 insertions(+), 24 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index f453c3a1e0f2c..672f64b27e432 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -83,7 +83,7 @@ public:
struct __layout;
__layout __data_;
- __split_buffer(const __split_buffer&) = delete;
+ __split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
@@ -91,14 +91,12 @@ public:
: __data_() {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_(__a)
- {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_(__a)
- {}
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __data_(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
@@ -424,32 +422,32 @@ __split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT
- -> pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::pointer
+__split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT {
return __first_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
-__split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT -> const_pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::const_pointer
+__split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT {
return __first_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto __split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT
- -> pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::pointer
+__split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT {
return __begin_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
-__split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT -> const_pointer {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::const_pointer
+__split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT {
return __begin_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI auto
-__split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT -> size_type {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::size_type
+__split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT {
return static_cast<size_type>(__begin_ - __first_);
}
@@ -492,7 +490,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __fi
size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
__split_buffer __buf(__new_cap, 0, __a);
pointer __buf_end = __buf.__data_.end();
- pointer __end = __data_.end();
+ pointer __end = __data_.end();
for (pointer __p = __data_.begin(); __p != __end; ++__p) {
__alloc_traits::construct(__buf.__data_.__alloc_, std::__to_address(__buf_end), std::move(*__p));
__buf.__data_.__update_sentinel(++__buf_end);
@@ -551,7 +549,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_typ
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
- : __data_(__a) {
+ : __data_(__a) {
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
auto __allocation = std::__allocate_at_least(__data_.__alloc_, __cap);
@@ -675,8 +673,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
#endif
}
-template<class _Tp, class _Allocator>
-template<class... _Args>
+template <class _Tp, class _Allocator>
+template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
pointer __end = __data_.end();
if (__data_.__back_spare() == 0) {
@@ -698,10 +696,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back
__data_.__update_sentinel(++__end);
}
-template<class _Tp, class _Allocator>
+template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
-swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
-{
+swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
__x.swap(__y);
}
>From 2c5f5e99ecedcc0b4efea98fc3f605158bfc7256 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 7 Jul 2025 18:45:39 +0000
Subject: [PATCH 10/28] more CI fixes
---
libcxx/include/__split_buffer | 14 +++++++-------
lldb/examples/synthetic/libcxx.py | 4 +++-
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 672f64b27e432..e7635a7cc93da 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -410,8 +410,8 @@ public:
#endif
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
-_LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+__split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
__first_ = __new_first;
}
@@ -422,31 +422,31 @@ __split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::pointer
__split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT {
return __first_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::const_pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::const_pointer
__split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT {
return __first_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::pointer
__split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT {
return __begin_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::const_pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::const_pointer
__split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT {
return __begin_;
}
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer<_Tp, _Allocator>::size_type
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::size_type
__split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT {
return static_cast<size_type>(__begin_ - __first_);
}
diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py
index 521bd06af5b3f..ff06df5f472f9 100644
--- a/lldb/examples/synthetic/libcxx.py
+++ b/lldb/examples/synthetic/libcxx.py
@@ -801,7 +801,9 @@ def update(self):
self.map_begin = map_.GetChildMemberWithName("__begin_")
map_begin = self.map_begin.GetValueAsUnsigned(0)
map_end = get_buffer_end(map_, map_begin)
- map_endcap = get_buffer_endcap(self, map_, map_begin, has_compressed_pair_layout, is_size_based)
+ map_endcap = get_buffer_endcap(
+ self, map_, map_begin, has_compressed_pair_layout, is_size_based
+ )
# check consistency
if not map_first <= map_begin <= map_end <= map_endcap:
>From c76a2a0093bd85c02a42ba3526c8f7d09a51e7a4 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 11 Jul 2025 18:39:20 +0000
Subject: [PATCH 11/28] refactors layout so that we can toggle it for both
vector and deque
---
libcxx/include/__split_buffer | 534 +++++++++++++++++-----------------
1 file changed, 264 insertions(+), 270 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index e7635a7cc93da..bf6735b8b99e7 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -47,11 +47,232 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
+template <class _SplitBuffer>
+class __split_buffer_pointer_layout {
+public: // TODO: make private after vector becomes size-based
+ using reference = typename _SplitBuffer::reference;
+ using const_reference = typename _SplitBuffer::const_reference;
+ using pointer = typename _SplitBuffer::pointer;
+ using const_pointer = typename _SplitBuffer::const_pointer;
+ using size_type = typename _SplitBuffer::size_type;
+ using allocator_type = typename _SplitBuffer::allocator_type;
+
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+
+public:
+ static const bool __is_size_based = false;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_pointer_layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20
+ _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_pointer_layout(const allocator_type& __alloc)
+ : __alloc_(__alloc) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT { return __first_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT { return __first_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT { return __begin_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __end_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __end_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __begin_ == __end_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __first_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT {
+ __first_ = __new_first;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
+ __begin_ = __new_begin;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__begin_ - __first_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ __end_ = __new_end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ __end_ = __begin_ + __new_size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ __cap_ = __first_ + __new_capacity;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __end_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return *(__end_ - 1); }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
+
+ template <class _OtherLayout>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_OtherLayout& __other) _NOEXCEPT {
+ std::swap(__first_, __other.__first_);
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__cap_, __other.__cap_);
+ std::swap(__end_, __other.__end_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer_pointer_layout& __other) _NOEXCEPT {
+ __swap_without_allocator(__other);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
+ __first_ = nullptr;
+ __begin_ = nullptr;
+ __end_ = nullptr;
+ __cap_ = nullptr;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __copy_without_alloc(__split_buffer_pointer_layout const& __other)
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
+ __first_ = __other.__first_;
+ __begin_ = __other.__begin_;
+ __cap_ = __other.__cap_;
+ __end_ = __other.__end_;
+ }
+};
+
+template <class _SplitBuffer>
+class __split_buffer_size_layout {
+public: // TODO: make private after vector becomes size-based
+ using reference = typename _SplitBuffer::reference;
+ using const_reference = typename _SplitBuffer::const_reference;
+ using pointer = typename _SplitBuffer::pointer;
+ using const_pointer = typename _SplitBuffer::const_pointer;
+ using size_type = typename _SplitBuffer::size_type;
+ using allocator_type = typename _SplitBuffer::allocator_type;
+
+ pointer __first_ = nullptr;
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ _LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
+
+public:
+ static const bool __is_size_based = true;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_size_layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_size_layout(const allocator_type& __alloc)
+ : __alloc_(__alloc) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT { return __first_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT { return __first_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT { return __begin_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __begin_ + __size_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __begin_ + __size_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT {
+ __first_ = __new_first;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _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;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__begin_ - __first_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ __size_ += __new_end - end();
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ __size_ = __new_size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ __cap_ = __new_capacity;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
+ // `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
+ // the __front_spare from the count.
+ return __cap_ - __size_ - __front_spare();
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return __begin_[__size_ - 1]; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ return __begin_[__size_ - 1];
+ }
+
+ template <class _Data2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
+ std::swap(__first_, __other.__first_);
+ std::swap(__begin_, __other.__begin_);
+ std::swap(__cap_, __other.__cap_);
+ std::swap(__size_, __other.__size_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer_size_layout& __other) _NOEXCEPT {
+ __swap_without_allocator(__other);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
+ __first_ = nullptr;
+ __begin_ = nullptr;
+ __size_ = 0;
+ __cap_ = 0;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __copy_without_alloc(__split_buffer_size_layout const& __other)
+ _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
+ __first_ = __other.__first_;
+ __begin_ = __other.__begin_;
+ __cap_ = __other.__cap_;
+ __size_ = __other.__size_;
+ }
+};
+
// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_).
// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows
// it to grow both in the front and back without having to move the data.
-template <class _Tp, class _Allocator = allocator<_Tp> >
+template <class _Tp, class _Allocator = allocator<_Tp>, template <class> class _Layout = __split_buffer_pointer_layout>
struct __split_buffer {
public:
using value_type = _Tp;
@@ -80,8 +301,7 @@ public:
__split_buffer,
void>;
- struct __layout;
- __layout __data_;
+ _Layout<__split_buffer> __data_;
__split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;
@@ -225,239 +445,13 @@ private:
};
};
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template <class _Tp, class _Allocatior>
-struct __split_buffer<_Tp, _Allocator>::__layout {
- // private:
- pointer __first_ = nullptr;
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- _LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
-
-public:
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
- : __alloc_(__alloc) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __begin_ + __size_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __begin_ + __size_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _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;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
- _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
- __size_ += __new_end - end();
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
- __size_ = __new_size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
- __cap_ = __new_capacity;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
- // `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
- // the __front_spare from the count.
- return __cap_ - __size_ - __front_spare();
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return __begin_[__size_ - 1]; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- return __begin_[__size_ - 1];
- }
-
- template <class _Data2>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
- std::swap(__first_, __other.__first_);
- std::swap(__begin_, __other.__begin_);
- std::swap(__cap_, __other.__cap_);
- std::swap(__size_, __other.__size_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__layout& __other) _NOEXCEPT {
- __swap_without_allocator(__other);
- std::__swap_allocator(__alloc_, __other.__alloc_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __first_ = nullptr;
- __begin_ = nullptr;
- __size_ = 0;
- __cap_ = 0;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
- _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __first_ = __other.__first_;
- __begin_ = __other.__begin_;
- __cap_ = __other.__cap_;
- __size_ = __other.__size_;
- }
-};
-#else
-template <class _Tp, class _Allocator>
-struct __split_buffer<_Tp, _Allocator>::__layout {
- // private:
- pointer __first_ = nullptr;
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-
-public:
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __layout() = default;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __layout(const allocator_type& __alloc)
- : __alloc_(__alloc) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __end_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __end_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(__end_ - __begin_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __begin_ == __end_; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __first_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
- _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
- __end_ = __new_end;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
- __end_ = __begin_ + __new_size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
- __cap_ = __first_ + __new_capacity;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __end_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return *(__end_ - 1); }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
-
- template <class _OtherLayout>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_OtherLayout& __other) _NOEXCEPT {
- std::swap(__first_, __other.__first_);
- std::swap(__begin_, __other.__begin_);
- std::swap(__cap_, __other.__cap_);
- std::swap(__end_, __other.__end_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__layout& __other) _NOEXCEPT {
- __swap_without_allocator(__other);
- std::__swap_allocator(__alloc_, __other.__alloc_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __first_ = nullptr;
- __begin_ = nullptr;
- __end_ = nullptr;
- __cap_ = nullptr;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_without_alloc(__layout const& __other)
- _NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __first_ = __other.__first_;
- __begin_ = __other.__begin_;
- __cap_ = __other.__cap_;
- __end_ = __other.__end_;
- }
-};
-#endif
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
-__split_buffer<_Tp, _Allocator>::__layout::__update_first(pointer __new_first) _NOEXCEPT {
- __first_ = __new_first;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
-__split_buffer<_Tp, _Allocator>::__layout::__update_begin(pointer __new_begin) _NOEXCEPT {
- __begin_ = __new_begin;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::pointer
-__split_buffer<_Tp, _Allocator>::__layout::first() _NOEXCEPT {
- return __first_;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::const_pointer
-__split_buffer<_Tp, _Allocator>::__layout::first() const _NOEXCEPT {
- return __first_;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::pointer
-__split_buffer<_Tp, _Allocator>::__layout::begin() _NOEXCEPT {
- return __begin_;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::const_pointer
-__split_buffer<_Tp, _Allocator>::__layout::begin() const _NOEXCEPT {
- return __begin_;
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename __split_buffer<_Tp, _Allocator>::size_type
-__split_buffer<_Tp, _Allocator>::__layout::__front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
-}
-
// Default constructs __n objects starting at `__begin_ + size()`
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
// Postcondition: size() == size() + __n
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) {
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n) {
_ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
__alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_));
@@ -470,19 +464,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_
// Precondition: size() + __n <= capacity()
// Postcondition: size() == old size() + __n
// Postcondition: [i] == __x for all i in [size() - __n, __n)
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
+__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n, const_reference __x) {
_ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
__alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), __x);
}
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
+__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
__alloc_rr& __a = __data_.__alloc_;
for (; __first != __last; ++__first) {
if (__data_.__back_spare() == 0) {
@@ -503,26 +497,26 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __fi
}
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) {
+__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) {
__construct_at_end_with_size(__first, std::distance(__first, __last));
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
template <class _ForwardIterator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
+__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
_ConstructTransaction __tx(this, __data_.end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) {
__alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), *__first);
}
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
-__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) {
+__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, false_type) {
pointer __begin = __data_.begin();
// Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
while (__begin != __new_begin)
@@ -530,15 +524,15 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_
__data_.__update_begin(__begin);
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
-__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) {
+__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, true_type) {
__data_.__update_begin(__new_begin);
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
-__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
+__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
pointer __end = __data_.end();
// Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
while (__new_last != __end)
@@ -546,9 +540,9 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_typ
__data_.__update_sentinel(__end);
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
+__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
: __data_(__a) {
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
@@ -562,23 +556,23 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta
__data_.__update_capacity(__cap);
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() {
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::~__split_buffer() {
clear();
if (__data_.first())
__alloc_traits::deallocate(__data_.__alloc_, __data_.first(), capacity());
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
: __data_(std::move(__c.__data_)) {
__c.__data_.__reset();
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
+__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __data_(__a) {
if (__a == __c.__data_.__alloc_) {
__data_.__update_first(__c.__data_.first());
@@ -597,9 +591,9 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __al
}
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>&
-__split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>&
+__split_buffer<_Tp, _Allocator, _Layout>::operator=(__split_buffer&& __c)
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
is_nothrow_move_assignable<allocator_type>::value) ||
!__alloc_traits::propagate_on_container_move_assignment::value) {
@@ -611,14 +605,14 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
return *this;
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::swap(__split_buffer& __x)
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
__data_.swap(__x.__data_);
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT {
+template <class _Tp, class _Allocator, template <class> class _Layout>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shrink_to_fit() _NOEXCEPT {
if (capacity() > size()) {
#if _LIBCPP_HAS_EXCEPTIONS
try {
@@ -636,9 +630,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
}
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
template <class... _Args>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_front(_Args&&... __args) {
if (__data_.__front_spare() == 0) {
pointer __end = __data_.end();
if (__data_.__back_spare() > 0) {
@@ -651,9 +645,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
// `__data_.begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
// the number of elements hasn't changed yet.
-#ifndef _LIBCPP_ABI_SIZE_BASED_VECTOR
- __data_.__update_sentinel(__data_.size() + __d);
-#endif
+ if constexpr (!_Layout<__split_buffer>::__is_size_based) {
+ __data_.__update_sentinel(__data_.size() + __d);
+ }
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __data_.__alloc_);
@@ -668,14 +662,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- __data_.__update_sentinel(__data_.end() + 1);
-#endif
+ if constexpr (_Layout<__split_buffer>::__is_size_based) {
+ __data_.__update_sentinel(__data_.end() + 1);
+ }
}
-template <class _Tp, class _Allocator>
+template <class _Tp, class _Allocator, template <class> class _Layout>
template <class... _Args>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_back(_Args&&... __args) {
pointer __end = __data_.end();
if (__data_.__back_spare() == 0) {
if (__data_.__front_spare() > 0) {
>From 80b0ad7e5a45f1bb89e8419f8d408ccbc8fe14bb Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 25 Jul 2025 07:00:13 +0000
Subject: [PATCH 12/28] replaces constexpr if with template specialisations for
C++03 compat
---
libcxx/include/__split_buffer | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index bf6735b8b99e7..2460b30235574 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -630,6 +630,32 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shr
}
}
+// Need to use this because C++03 doesn't permit constexpr if :(
+template<bool>
+struct __maybe_update_sentinel;
+
+template<>
+struct __maybe_update_sentinel<true> {
+ template<class _SplitBuffer, class _DifferenceType>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer& __data, _DifferenceType __d) {
+ __data.__update_sentinel(__data.size() + __d);
+ }
+
+ template<class _SplitBuffer>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer& __data) {
+ __data.update_sentinel(__data.end() + 1);
+ }
+};
+
+template<>
+struct __maybe_update_sentinel<false> {
+ template<class _SplitBuffer, class _DifferenceType>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer&, _DifferenceType) {}
+
+ template<class _SplitBuffer>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer&) {}
+};
+
template <class _Tp, class _Allocator, template <class> class _Layout>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_front(_Args&&... __args) {
@@ -645,9 +671,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// `__data_.begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
// the number of elements hasn't changed yet.
- if constexpr (!_Layout<__split_buffer>::__is_size_based) {
- __data_.__update_sentinel(__data_.size() + __d);
- }
+ __maybe_update_sentinel<!_Layout<__split_buffer>::__is_size_based>::__update_size(__data_, __d);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __data_.__alloc_);
@@ -662,10 +686,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
- if constexpr (_Layout<__split_buffer>::__is_size_based) {
- __data_.__update_sentinel(__data_.end() + 1);
+ __maybe_update_sentinel<_Layout<__split_buffer>::__is_size_based>::__update_end(__data_);
}
-}
template <class _Tp, class _Allocator, template <class> class _Layout>
template <class... _Args>
>From 8cbc2dcd6e87597741d571a55d946caf65d0603c Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 25 Jul 2025 07:06:50 +0000
Subject: [PATCH 13/28] clang-format
---
libcxx/include/__split_buffer | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 2460b30235574..f975860e326f0 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -631,28 +631,28 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shr
}
// Need to use this because C++03 doesn't permit constexpr if :(
-template<bool>
+template <bool>
struct __maybe_update_sentinel;
-template<>
+template <>
struct __maybe_update_sentinel<true> {
- template<class _SplitBuffer, class _DifferenceType>
+ template <class _SplitBuffer, class _DifferenceType>
_LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer& __data, _DifferenceType __d) {
__data.__update_sentinel(__data.size() + __d);
}
- template<class _SplitBuffer>
+ template <class _SplitBuffer>
_LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer& __data) {
__data.update_sentinel(__data.end() + 1);
}
};
-template<>
+template <>
struct __maybe_update_sentinel<false> {
- template<class _SplitBuffer, class _DifferenceType>
+ template <class _SplitBuffer, class _DifferenceType>
_LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer&, _DifferenceType) {}
- template<class _SplitBuffer>
+ template <class _SplitBuffer>
_LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer&) {}
};
@@ -687,7 +687,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
__maybe_update_sentinel<_Layout<__split_buffer>::__is_size_based>::__update_end(__data_);
- }
+}
template <class _Tp, class _Allocator, template <class> class _Layout>
template <class... _Args>
>From e60cbb1cb60c283044958dff3b51cf30a57162bc Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Fri, 25 Jul 2025 07:26:51 +0000
Subject: [PATCH 14/28] updates for new CI jobs
---
libcxx/include/__split_buffer | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index f975860e326f0..a3557fc792947 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -637,12 +637,13 @@ struct __maybe_update_sentinel;
template <>
struct __maybe_update_sentinel<true> {
template <class _SplitBuffer, class _DifferenceType>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer& __data, _DifferenceType __d) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void
+ __update_size(_SplitBuffer& __data, _DifferenceType __d) {
__data.__update_sentinel(__data.size() + __d);
}
template <class _SplitBuffer>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer& __data) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_end(_SplitBuffer& __data) {
__data.update_sentinel(__data.end() + 1);
}
};
@@ -650,10 +651,10 @@ struct __maybe_update_sentinel<true> {
template <>
struct __maybe_update_sentinel<false> {
template <class _SplitBuffer, class _DifferenceType>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_size(_SplitBuffer&, _DifferenceType) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_size(_SplitBuffer&, _DifferenceType) {}
template <class _SplitBuffer>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __update_end(_SplitBuffer&) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_end(_SplitBuffer&) {}
};
template <class _Tp, class _Allocator, template <class> class _Layout>
>From 9c0ca507f332646fb92096aa4d61ad1c5c9569dd Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 31 Jul 2025 16:50:54 +0000
Subject: [PATCH 15/28] adds docs for pretty-printer
---
lldb/examples/synthetic/libcxx.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py
index ff06df5f472f9..e2932d8f54019 100644
--- a/lldb/examples/synthetic/libcxx.py
+++ b/lldb/examples/synthetic/libcxx.py
@@ -87,6 +87,12 @@ def get_buffer_data(parent):
def get_buffer_end(buffer, begin):
+ """
+ Returns a pointer to where the next element would be pushed.
+
+ For libc++'s stable ABI and unstable < LLVM 22, returns `__end_`.
+ For libc++'s unstable ABI, returns `__begin_ + __size_`.
+ """
map_end = buffer.GetChildMemberWithName("__end_")
if map_end.IsValid():
return map_end.GetValueAsUnsigned(0)
@@ -95,6 +101,14 @@ def get_buffer_end(buffer, begin):
def get_buffer_endcap(parent, buffer, begin, has_compressed_pair_layout, is_size_based):
+ """
+ Returns a pointer to the end of the buffer.
+
+ For libc++'s stable ABI and unstable < LLVM 22, returns:
+ * `__end_cap_`, if `__compressed_pair` is being used
+ * `__cap_`, otherwise
+ For libc++'s unstable ABI, returns `__begin_ + __cap_`.
+ """
if has_compressed_pair_layout:
map_endcap = parent._get_value_of_compressed_pair(
buffer.GetChildMemberWithName("__end_cap_")
>From c1960d994e623b84183f0b0f69f01f86b1899ef6 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 17:19:53 +0000
Subject: [PATCH 16/28] makes `_Layout` a base class instead of a data member
---
libcxx/include/__split_buffer | 331 ++++++++++++++++---------------
libcxx/include/__vector/vector.h | 30 +--
libcxx/include/deque | 28 +--
3 files changed, 201 insertions(+), 188 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index a3557fc792947..beb7f2c82ff1c 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -47,16 +47,22 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _SplitBuffer>
+template <class _SplitBuffer, class _Tp, class _Allocator>
class __split_buffer_pointer_layout {
+protected:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>;
+ 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 iterator = pointer;
+ using const_iterator = const_pointer;
public: // TODO: make private after vector becomes size-based
- using reference = typename _SplitBuffer::reference;
- using const_reference = typename _SplitBuffer::const_reference;
- using pointer = typename _SplitBuffer::pointer;
- using const_pointer = typename _SplitBuffer::const_pointer;
- using size_type = typename _SplitBuffer::size_type;
- using allocator_type = typename _SplitBuffer::allocator_type;
-
pointer __first_ = nullptr;
pointer __begin_ = nullptr;
pointer __end_ = nullptr;
@@ -156,16 +162,23 @@ public:
}
};
-template <class _SplitBuffer>
+template <class _SplitBuffer, class _Tp, class _Allocator>
class __split_buffer_size_layout {
-public: // TODO: make private after vector becomes size-based
- using reference = typename _SplitBuffer::reference;
- using const_reference = typename _SplitBuffer::const_reference;
- using pointer = typename _SplitBuffer::pointer;
- using const_pointer = typename _SplitBuffer::const_pointer;
- using size_type = typename _SplitBuffer::size_type;
- using allocator_type = typename _SplitBuffer::allocator_type;
+protected:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>;
+ 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 iterator = pointer;
+ using const_iterator = const_pointer;
+public: // TODO: make private after vector becomes size-based
pointer __first_ = nullptr;
pointer __begin_ = nullptr;
size_type __size_ = 0;
@@ -272,21 +285,31 @@ public:
// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows
// it to grow both in the front and back without having to move the data.
-template <class _Tp, class _Allocator = allocator<_Tp>, template <class> class _Layout = __split_buffer_pointer_layout>
-struct __split_buffer {
+template <class _Tp, class _Allocator = allocator<_Tp>, template <class, class, class> class _Layout = __split_buffer_pointer_layout>
+struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
+ using __base_type = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
+ using __base_type::first;
+ using __base_type::__update_first;
+ using __base_type::__update_begin;
+ using __base_type::__update_capacity;
+ using __base_type::__update_sentinel;
+ using __base_type::__front_spare;
+ using __base_type::__back_spare;
+ using __base_type::__reset;
+ using __base_type::__swap_without_allocator;
public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>;
- 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 iterator = pointer;
- using const_iterator = const_pointer;
+ using typename __base_type::value_type;
+ using typename __base_type::allocator_type;
+ using typename __base_type::__alloc_rr;
+ using typename __base_type::__alloc_traits;
+ using typename __base_type::reference;
+ using typename __base_type::const_reference;
+ using typename __base_type::size_type;
+ using typename __base_type::difference_type;
+ using typename __base_type::pointer;
+ using typename __base_type::const_pointer;
+ using typename __base_type::iterator;
+ using typename __base_type::const_iterator;
// A __split_buffer contains the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
@@ -301,22 +324,18 @@ public:
__split_buffer,
void>;
- _Layout<__split_buffer> __data_;
-
__split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_() {}
+ _LIBCPP_HIDE_FROM_ABI __split_buffer() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_(__a) {}
+ : __base_type(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_(__a) {}
+ : __base_type(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
@@ -333,22 +352,16 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __data_.begin(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __data_.begin(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __data_.end(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __data_.end(); }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__data_.begin()); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const { return __data_.size(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __data_.empty(); }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { return __data_.capacity(); }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__data_.begin(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__data_.begin(); }
+ using __base_type::begin;
+ using __base_type::end;
+ using __base_type::size;
+ using __base_type::empty;
+ using __base_type::capacity;
+ using __base_type::back;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return __data_.back(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return __data_.back(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(begin()); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *begin(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *begin(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -357,8 +370,8 @@ public:
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__data_.begin() + 1); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__data_.end() - 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(begin() + 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(end() - 1); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
@@ -393,25 +406,25 @@ public:
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__data_.first() == nullptr) {
- if (__data_.begin() != nullptr)
+ if (first() == nullptr) {
+ if (begin() != nullptr)
return false;
- if (!__data_.empty())
+ if (!empty())
return false;
- if (__data_.capacity() != 0)
+ if (capacity() != 0)
return false;
return true;
} else {
- if (__data_.begin() < __data_.first())
+ if (begin() < first())
return false;
- if (__data_.capacity() < __data_.size())
+ if (capacity() < size())
return false;
- if (__data_.end() < __data_.begin())
+ if (end() < begin())
return false;
return true;
@@ -421,7 +434,7 @@ public:
private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __data_.__alloc_ = std::move(__c.__data_.__alloc_);
+ this->__alloc_ = std::move(__c.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {}
@@ -434,7 +447,7 @@ private:
__parent_(__parent) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __parent_->__data_.__update_sentinel(__pos_);
+ __parent_->__update_sentinel(__pos_);
}
pointer __pos_;
@@ -450,11 +463,11 @@ private:
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
// Postcondition: size() == size() + __n
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n) {
- _ConstructTransaction __tx(this, __data_.end(), __n);
+ _ConstructTransaction __tx(this, end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_));
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_));
}
}
@@ -464,134 +477,134 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::__c
// Precondition: size() + __n <= capacity()
// Postcondition: size() == old size() + __n
// Postcondition: [i] == __x for all i in [size() - __n, __n)
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n, const_reference __x) {
- _ConstructTransaction __tx(this, __data_.end(), __n);
+ _ConstructTransaction __tx(this, end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), __x);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), __x);
}
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
- __alloc_rr& __a = __data_.__alloc_;
+ __alloc_rr& __a = this->__alloc_;
for (; __first != __last; ++__first) {
- if (__data_.__back_spare() == 0) {
- size_type __old_cap = __data_.capacity();
+ if (__back_spare() == 0) {
+ size_type __old_cap = capacity();
size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
__split_buffer __buf(__new_cap, 0, __a);
- pointer __buf_end = __buf.__data_.end();
- pointer __end = __data_.end();
- for (pointer __p = __data_.begin(); __p != __end; ++__p) {
- __alloc_traits::construct(__buf.__data_.__alloc_, std::__to_address(__buf_end), std::move(*__p));
- __buf.__data_.__update_sentinel(++__buf_end);
+ pointer __buf_end = __buf.end();
+ pointer __end = end();
+ for (pointer __p = begin(); __p != __end; ++__p) {
+ __alloc_traits::construct(__buf.__alloc_, std::__to_address(__buf_end), std::move(*__p));
+ __buf.__update_sentinel(++__buf_end);
}
swap(__buf);
}
- __alloc_traits::construct(__a, std::__to_address(__data_.end()), *__first);
- __data_.__update_sentinel(size() + 1);
+ __alloc_traits::construct(__a, std::__to_address(end()), *__first);
+ __update_sentinel(size() + 1);
}
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) {
__construct_at_end_with_size(__first, std::distance(__first, __last));
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class _ForwardIterator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
- _ConstructTransaction __tx(this, __data_.end(), __n);
+ _ConstructTransaction __tx(this, end(), __n);
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) {
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__tx.__pos_), *__first);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), *__first);
}
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, false_type) {
- pointer __begin = __data_.begin();
- // Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
+ pointer __begin = begin();
+ // Updating begin at every iteration is unnecessary because destruction can't throw.
while (__begin != __new_begin)
- __alloc_traits::destroy(__data_.__alloc_, std::__to_address(__begin++));
- __data_.__update_begin(__begin);
+ __alloc_traits::destroy(this->__alloc_, std::__to_address(__begin++));
+ __update_begin(__begin);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, true_type) {
- __data_.__update_begin(__new_begin);
+ __update_begin(__new_begin);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
- pointer __end = __data_.end();
- // Updating __data_'s begin at every iteration is unnecessary because destruction can't throw.
+ pointer __end = end();
+ // Updating begin at every iteration is unnecessary because destruction can't throw.
while (__new_last != __end)
- __alloc_traits::destroy(__data_.__alloc_, std::__to_address(--__end));
- __data_.__update_sentinel(__end);
+ __alloc_traits::destroy(this->__alloc_, std::__to_address(--__end));
+ __update_sentinel(__end);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
- : __data_(__a) {
+ : __base_type(__a) {
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
- auto __allocation = std::__allocate_at_least(__data_.__alloc_, __cap);
- __data_.__update_first(__allocation.ptr);
+ auto __allocation = std::__allocate_at_least(this->__alloc_, __cap);
+ __update_first(__allocation.ptr);
__cap = __allocation.count;
}
- __data_.__update_begin(__data_.first() + __start);
- __data_.__update_sentinel(__data_.begin());
- __data_.__update_capacity(__cap);
+ __update_begin(first() + __start);
+ __update_sentinel(begin());
+ __update_capacity(__cap);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::~__split_buffer() {
clear();
- if (__data_.first())
- __alloc_traits::deallocate(__data_.__alloc_, __data_.first(), capacity());
+ if (first())
+ __alloc_traits::deallocate(this->__alloc_, first(), capacity());
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __data_(std::move(__c.__data_)) {
- __c.__data_.__reset();
+ : __base_type(std::move(__c)) {
+ __c.__reset();
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
- : __data_(__a) {
- if (__a == __c.__data_.__alloc_) {
- __data_.__update_first(__c.__data_.first());
- __data_.__update_begin(__c.__data_.begin());
- __data_.__update_sentinel(__c.__data_.end());
- __data_.__update_capacity(__c.__data_.capacity());
- __c.__data_.__reset();
+ : __base_type(__a) {
+ if (__a == __c.__alloc_) {
+ __update_first(first());
+ __update_begin(begin());
+ __update_sentinel(end());
+ __update_capacity(capacity());
+ __reset();
} else {
- auto __allocation = std::__allocate_at_least(__data_.__alloc_, __c.size());
- __data_.__update_first(__allocation.ptr);
- __data_.__update_begin(__data_.first());
- __data_.__update_sentinel(__data_.first());
- __data_.__update_capacity(__allocation.count);
+ auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
+ __update_first(__allocation.ptr);
+ __update_begin(first());
+ __update_sentinel(this->first());
+ __update_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
}
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>&
__split_buffer<_Tp, _Allocator, _Layout>::operator=(__split_buffer&& __c)
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
@@ -599,29 +612,29 @@ __split_buffer<_Tp, _Allocator, _Layout>::operator=(__split_buffer&& __c)
!__alloc_traits::propagate_on_container_move_assignment::value) {
clear();
shrink_to_fit();
- __data_.__copy_without_alloc(__c.__data_);
+ __copy_without_alloc(__c);
__move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
- __c.__data_.__reset();
+ __c.__reset();
return *this;
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::swap(__split_buffer& __x)
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
- __data_.swap(__x.__data_);
+ __base_type::swap(__x);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shrink_to_fit() _NOEXCEPT {
if (capacity() > size()) {
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __data_.__alloc_);
+ __split_buffer<value_type, __alloc_rr&> __t(size(), 0, this->__alloc_);
if (__t.capacity() < capacity()) {
- __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__data_.end()));
- __t.__data_.__update_sentinel(__data_.size());
- __data_.__swap_without_allocator(__t.__data_);
+ __t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(end()));
+ __t.__update_sentinel(size());
+ __swap_without_allocator(__t);
}
#if _LIBCPP_HAS_EXCEPTIONS
} catch (...) {
@@ -657,60 +670,60 @@ struct __maybe_update_sentinel<false> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_end(_SplitBuffer&) {}
};
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_front(_Args&&... __args) {
- if (__data_.__front_spare() == 0) {
- pointer __end = __data_.end();
- if (__data_.__back_spare() > 0) {
+ if (__front_spare() == 0) {
+ pointer __end = end();
+ if (__back_spare() > 0) {
// The elements are pressed up against the front of the buffer: we need to move them back a
// little bit to make `emplace_front` have amortised O(1) complexity.
- difference_type __d = __data_.__back_spare();
+ difference_type __d = __back_spare();
__d = (__d + 1) / 2;
- __data_.__update_begin(std::move_backward(__data_.begin(), __end, __end + __d));
+ __update_begin(std::move_backward(begin(), __end, __end + __d));
- // `__data_.begin()` was moved further into the buffer, so we need to update the pointer-based
+ // `begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
// the number of elements hasn't changed yet.
- __maybe_update_sentinel<!_Layout<__split_buffer>::__is_size_based>::__update_size(__data_, __d);
+ __maybe_update_sentinel<!_Layout<__split_buffer, _Tp, _Allocator>::__is_size_based>::__update_size(*this, __d);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
- __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __data_.__alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__end));
- __data_.__swap_without_allocator(__t.__data_);
+ __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, this->__alloc_);
+ __t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
+ __swap_without_allocator(__t);
}
}
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__data_.begin() - 1), std::forward<_Args>(__args)...);
- __data_.__update_begin(__data_.begin() - 1);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(begin() - 1), std::forward<_Args>(__args)...);
+ __update_begin(begin() - 1);
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
- __maybe_update_sentinel<_Layout<__split_buffer>::__is_size_based>::__update_end(__data_);
+ __maybe_update_sentinel<_Layout<__split_buffer, _Tp, _Allocator>::__is_size_based>::__update_end(*this);
}
-template <class _Tp, class _Allocator, template <class> class _Layout>
+template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_back(_Args&&... __args) {
- pointer __end = __data_.end();
- if (__data_.__back_spare() == 0) {
- if (__data_.__front_spare() > 0) {
- difference_type __d = __data_.__front_spare();
+ pointer __end = end();
+ if (__back_spare() == 0) {
+ if (__front_spare() > 0) {
+ difference_type __d = __front_spare();
__d = (__d + 1) / 2;
- __end = std::move(__data_.begin(), __end, __data_.begin() - __d);
- __data_.__update_begin(__data_.begin() - __d);
- __data_.__update_sentinel(__end);
+ __end = std::move(begin(), __end, begin() - __d);
+ __update_begin(begin() - __d);
+ __update_sentinel(__end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
- __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __data_.__alloc_);
- __t.__construct_at_end(move_iterator<pointer>(__data_.begin()), move_iterator<pointer>(__end));
- __data_.__swap_without_allocator(__t.__data_);
+ __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, this->__alloc_);
+ __t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
+ __swap_without_allocator(__t);
}
}
- __alloc_traits::construct(__data_.__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
- __data_.__update_sentinel(++__end);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __update_sentinel(++__end);
}
template <class _Tp, class _Allocator>
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 1f7c9c9bcbf89..42191bd666f44 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -853,13 +853,13 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
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));
- __v.__data_.__begin_ = __new_begin;
+ __v.__begin_ = __new_begin;
__end_ = __begin_; // All the objects have been destroyed by relocating them.
- std::swap(this->__begin_, __v.__data_.__begin_);
- std::swap(this->__end_, __v.__data_.__end_);
- std::swap(this->__cap_, __v.__data_.__cap_);
- __v.__data_.__update_first(__v.begin());
+ std::swap(this->__begin_, __v.__begin_);
+ std::swap(this->__end_, __v.__end_);
+ std::swap(this->__cap_, __v.__cap_);
+ __v.__update_first(__v.begin());
__annotate_new(size());
}
@@ -878,18 +878,18 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
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;
- __v.__data_.__update_sentinel(__v.end() + __relocated_so_far);
+ __v.__update_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_);
std::__uninitialized_allocator_relocate(
this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__data_.__begin_ = __new_begin;
+ __v.__begin_ = __new_begin;
__end_ = __begin_; // All the objects have been destroyed by relocating them.
- std::swap(this->__begin_, __v.__data_.__begin_);
- std::swap(this->__end_, __v.__data_.__end_);
- std::swap(this->__cap_, __v.__data_.__cap_);
- __v.__data_.__first_ = __v.begin();
+ std::swap(this->__begin_, __v.__begin_);
+ std::swap(this->__end_, __v.__end_);
+ std::swap(this->__cap_, __v.__cap_);
+ __v.__first_ = __v.begin();
__annotate_new(size());
return __ret;
}
@@ -1139,7 +1139,7 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
- __v.__data_.__update_sentinel(++__end);
+ __v.__update_sentinel(++__end);
__swap_out_circular_buffer(__v);
return this->__end_;
}
@@ -1316,12 +1316,12 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
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.__data_.__update_sentinel(__merged.end() + (this->__end_ - __old_last));
+ __merged.__update_sentinel(__merged.end() + (this->__end_ - __old_last));
this->__end_ = __old_last;
std::__uninitialized_allocator_relocate(
__alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
- __merged.__data_.__update_sentinel(__merged.size() + __v.size());
- __v.__data_.__update_sentinel(__v.begin());
+ __merged.__update_sentinel(__merged.size() + __v.size());
+ __v.__update_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
}
return __make_iter(__p);
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 91688f9f76508..3fb87be25159a 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1239,7 +1239,7 @@ private:
shrink_to_fit();
}
__alloc() = __c.__alloc();
- __map_.__data_.__alloc_ = __c.__map_.__data_.__alloc_;
+ __map_.__alloc_ = __c.__map_.__alloc_;
}
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const deque&, false_type) {}
@@ -1318,7 +1318,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c)
: __map_(__pointer_allocator(__alloc_traits::select_on_container_copy_construction(__c.__alloc()))),
__start_(0),
__size_(0),
- __alloc_(__map_.__data_.__alloc_) {
+ __alloc_(__map_.__alloc_) {
__annotate_new(0);
__append(__c.begin(), __c.end());
}
@@ -2057,7 +2057,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
- if (__map_.__data_.__front_spare() > 0)
+ if (__map_.__front_spare() > 0)
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
else {
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
@@ -2071,7 +2071,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
// Else need to allocate 1 buffer, *and* we need to reallocate __map_.
else {
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), 1), 0, __map_.__data_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), 1), 0, __map_.__alloc_);
typedef __allocator_destructor<_Allocator> _Dp;
unique_ptr<pointer, _Dp> __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size));
@@ -2080,7 +2080,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i)
__buf.emplace_back(*__i);
- __map_.__data_.__swap_without_allocator(__buf.__data_);
+ __map_.__swap_without_allocator(__buf);
__start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size;
}
__annotate_whole_block(0, __asan_poison);
@@ -2111,7 +2111,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
for (; __nb > 0; --__nb, __start_ += __block_size - (__map_.size() == 1)) {
- if (__map_.__data_.__front_spare() == 0)
+ if (__map_.__front_spare() == 0)
break;
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
__annotate_whole_block(0, __asan_poison);
@@ -2131,7 +2131,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
else {
size_type __ds = (__nb + __back_capacity) * __block_size - __map_.empty();
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__data_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__alloc_);
# if _LIBCPP_HAS_EXCEPTIONS
try {
# endif // _LIBCPP_HAS_EXCEPTIONS
@@ -2154,7 +2154,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) {
}
for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i)
__buf.emplace_back(*__i);
- __map_.__data_.__swap_without_allocator(__buf.__data_);
+ __map_.__swap_without_allocator(__buf);
__start_ += __ds;
}
}
@@ -2174,7 +2174,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around
// until it is allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
- if (__map_.__data_.__back_spare() != 0)
+ if (__map_.__back_spare() != 0)
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
else {
__map_.emplace_front(__alloc_traits::allocate(__a, __block_size));
@@ -2188,7 +2188,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
// Else need to allocate 1 buffer, *and* we need to reallocate __map_.
else {
__split_buffer<pointer, __pointer_allocator&> __buf(
- std::max<size_type>(2 * __map_.capacity(), 1), __map_.size(), __map_.__data_.__alloc_);
+ std::max<size_type>(2 * __map_.capacity(), 1), __map_.size(), __map_.__alloc_);
typedef __allocator_destructor<_Allocator> _Dp;
unique_ptr<pointer, _Dp> __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size));
@@ -2197,7 +2197,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() {
for (__map_pointer __i = __map_.end(); __i != __map_.begin();)
__buf.emplace_front(*--__i);
- __map_.__data_.__swap_without_allocator(__buf.__data_);
+ __map_.__swap_without_allocator(__buf);
__annotate_whole_block(__map_.size() - 1, __asan_poison);
}
}
@@ -2227,7 +2227,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
// until all buffers are allocated. If we throw, we don't need to fix
// anything up (any added buffers are undetectible)
for (; __nb > 0; --__nb) {
- if (__map_.__data_.__back_spare() == 0)
+ if (__map_.__back_spare() == 0)
break;
__map_.emplace_back(__alloc_traits::allocate(__a, __block_size));
__annotate_whole_block(__map_.size() - 1, __asan_poison);
@@ -2250,7 +2250,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
__split_buffer<pointer, __pointer_allocator&> __buf(
std::max<size_type>(2 * __map_.capacity(), __nb + __map_.size()),
__map_.size() - __front_capacity,
- __map_.__data_.__alloc_);
+ __map_.__alloc_);
# if _LIBCPP_HAS_EXCEPTIONS
try {
# endif // _LIBCPP_HAS_EXCEPTIONS
@@ -2273,7 +2273,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) {
}
for (__map_pointer __i = __map_.end(); __i != __map_.begin();)
__buf.emplace_front(*--__i);
- __map_.__data_.__swap_without_allocator(__buf.__data_);
+ __map_.__swap_without_allocator(__buf);
__start_ -= __ds;
}
}
>From 237e90075d218c1a98bc5a5c8656880ae55f4baa Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 17:53:03 +0000
Subject: [PATCH 17/28] renames `__update_*` to `__set_*`
---
libcxx/include/__split_buffer | 80 ++++++++++++++++----------------
libcxx/include/__vector/vector.h | 12 ++---
2 files changed, 47 insertions(+), 45 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index beb7f2c82ff1c..5ecb6a2e4265e 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -99,11 +99,11 @@ public:
return static_cast<size_type>(__cap_ - __first_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_first(pointer __new_first) _NOEXCEPT {
__first_ = __new_first;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_begin(pointer __new_begin) _NOEXCEPT {
__begin_ = __new_begin;
}
@@ -111,16 +111,16 @@ public:
return static_cast<size_type>(__begin_ - __first_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
_LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
__end_ = __new_end;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __new_size) _NOEXCEPT {
__end_ = __begin_ + __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __first_ + __new_capacity;
}
@@ -211,11 +211,11 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_first(pointer __new_first) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_first(pointer __new_first) _NOEXCEPT {
__first_ = __new_first;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_begin(pointer __new_begin) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_begin(pointer __new_begin) _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_;
@@ -226,16 +226,16 @@ public:
return static_cast<size_type>(__begin_ - __first_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(pointer __new_end) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
_LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
__size_ += __new_end - end();
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_sentinel(size_type __new_size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __new_size) _NOEXCEPT {
__size_ = __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __update_capacity(size_type __new_capacity) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __new_capacity;
}
@@ -289,15 +289,17 @@ template <class _Tp, class _Allocator = allocator<_Tp>, template <class, class,
struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
using __base_type = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
using __base_type::first;
- using __base_type::__update_first;
- using __base_type::__update_begin;
- using __base_type::__update_capacity;
- using __base_type::__update_sentinel;
+ using __base_type::__set_first;
+ using __base_type::__set_begin;
+ using __base_type::__set_capacity;
+ using __base_type::__set_sentinel;
+ using __base_type::__set_size_if_size_based;
+ using __base_type::__set_end_if_pointer_based;
using __base_type::__front_spare;
using __base_type::__back_spare;
using __base_type::__reset;
using __base_type::__swap_without_allocator;
-public:
+
using typename __base_type::value_type;
using typename __base_type::allocator_type;
using typename __base_type::__alloc_rr;
@@ -447,7 +449,7 @@ private:
__parent_(__parent) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __parent_->__update_sentinel(__pos_);
+ __parent_->__set_sentinel(__pos_);
}
pointer __pos_;
@@ -500,13 +502,13 @@ __split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_sentinel(_Iter
pointer __end = end();
for (pointer __p = begin(); __p != __end; ++__p) {
__alloc_traits::construct(__buf.__alloc_, std::__to_address(__buf_end), std::move(*__p));
- __buf.__update_sentinel(++__buf_end);
+ __buf.__set_sentinel(++__buf_end);
}
swap(__buf);
}
__alloc_traits::construct(__a, std::__to_address(end()), *__first);
- __update_sentinel(size() + 1);
+ __set_sentinel(size() + 1);
}
}
@@ -534,13 +536,13 @@ __split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begi
// Updating begin at every iteration is unnecessary because destruction can't throw.
while (__begin != __new_begin)
__alloc_traits::destroy(this->__alloc_, std::__to_address(__begin++));
- __update_begin(__begin);
+ __set_begin(__begin);
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, true_type) {
- __update_begin(__new_begin);
+ __set_begin(__new_begin);
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -550,7 +552,7 @@ __split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_end(pointer __new_last,
// Updating begin at every iteration is unnecessary because destruction can't throw.
while (__new_last != __end)
__alloc_traits::destroy(this->__alloc_, std::__to_address(--__end));
- __update_sentinel(__end);
+ __set_sentinel(__end);
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -560,13 +562,13 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
auto __allocation = std::__allocate_at_least(this->__alloc_, __cap);
- __update_first(__allocation.ptr);
+ __set_first(__allocation.ptr);
__cap = __allocation.count;
}
- __update_begin(first() + __start);
- __update_sentinel(begin());
- __update_capacity(__cap);
+ __set_begin(first() + __start);
+ __set_sentinel(begin());
+ __set_capacity(__cap);
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -588,17 +590,17 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __base_type(__a) {
if (__a == __c.__alloc_) {
- __update_first(first());
- __update_begin(begin());
- __update_sentinel(end());
- __update_capacity(capacity());
+ __set_first(first());
+ __set_begin(begin());
+ __set_sentinel(end());
+ __set_capacity(capacity());
__reset();
} else {
auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
- __update_first(__allocation.ptr);
- __update_begin(first());
- __update_sentinel(this->first());
- __update_capacity(__allocation.count);
+ __set_first(__allocation.ptr);
+ __set_begin(first());
+ __set_sentinel(this->first());
+ __set_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
}
@@ -633,7 +635,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shr
__split_buffer<value_type, __alloc_rr&> __t(size(), 0, this->__alloc_);
if (__t.capacity() < capacity()) {
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(end()));
- __t.__update_sentinel(size());
+ __t.__set_sentinel(size());
__swap_without_allocator(__t);
}
#if _LIBCPP_HAS_EXCEPTIONS
@@ -680,7 +682,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// little bit to make `emplace_front` have amortised O(1) complexity.
difference_type __d = __back_spare();
__d = (__d + 1) / 2;
- __update_begin(std::move_backward(begin(), __end, __end + __d));
+ __set_begin(std::move_backward(begin(), __end, __end + __d));
// `begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
@@ -695,7 +697,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
}
__alloc_traits::construct(this->__alloc_, std::__to_address(begin() - 1), std::forward<_Args>(__args)...);
- __update_begin(begin() - 1);
+ __set_begin(begin() - 1);
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
@@ -712,8 +714,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
difference_type __d = __front_spare();
__d = (__d + 1) / 2;
__end = std::move(begin(), __end, begin() - __d);
- __update_begin(begin() - __d);
- __update_sentinel(__end);
+ __set_begin(begin() - __d);
+ __set_sentinel(__end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, this->__alloc_);
@@ -723,7 +725,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
}
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
- __update_sentinel(++__end);
+ __set_sentinel(++__end);
}
template <class _Tp, class _Allocator>
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 42191bd666f44..31ac508c2f087 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -859,7 +859,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
std::swap(this->__begin_, __v.__begin_);
std::swap(this->__end_, __v.__end_);
std::swap(this->__cap_, __v.__cap_);
- __v.__update_first(__v.begin());
+ __v.__set_first(__v.begin());
__annotate_new(size());
}
@@ -878,7 +878,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
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;
- __v.__update_sentinel(__v.end() + __relocated_so_far);
+ __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_);
@@ -1139,7 +1139,7 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
- __v.__update_sentinel(++__end);
+ __v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
return this->__end_;
}
@@ -1316,12 +1316,12 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
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.__update_sentinel(__merged.end() + (this->__end_ - __old_last));
+ __merged.__set_sentinel(__merged.end() + (this->__end_ - __old_last));
this->__end_ = __old_last;
std::__uninitialized_allocator_relocate(
__alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
- __merged.__update_sentinel(__merged.size() + __v.size());
- __v.__update_sentinel(__v.begin());
+ __merged.__set_sentinel(__merged.size() + __v.size());
+ __v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
}
return __make_iter(__p);
>From 10260d3eee82a698bb0f77b8f13f09d21213f565 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 17:54:22 +0000
Subject: [PATCH 18/28] moves `__maybe_update` into layout types
---
libcxx/include/__split_buffer | 47 +++++++++++------------------------
1 file changed, 14 insertions(+), 33 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 5ecb6a2e4265e..2c315a6f46f5d 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -69,8 +69,6 @@ public: // TODO: make private after vector becomes size-based
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
public:
- static const bool __is_size_based = false;
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_pointer_layout() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -120,6 +118,13 @@ public:
__end_ = __begin_ + __new_size;
}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type __d) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() {
+ __set_sentinel(end() + 1);
+ }
+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __first_ + __new_capacity;
}
@@ -186,8 +191,6 @@ public: // TODO: make private after vector becomes size-based
_LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
public:
- static const bool __is_size_based = true;
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_size_layout() = default;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_size_layout(const allocator_type& __alloc)
@@ -235,6 +238,11 @@ public:
__size_ = __new_size;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type __d) {
+ __set_sentinel(size() + __d);
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() {}
+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __new_capacity;
}
@@ -645,33 +653,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shr
}
}
-// Need to use this because C++03 doesn't permit constexpr if :(
-template <bool>
-struct __maybe_update_sentinel;
-
-template <>
-struct __maybe_update_sentinel<true> {
- template <class _SplitBuffer, class _DifferenceType>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void
- __update_size(_SplitBuffer& __data, _DifferenceType __d) {
- __data.__update_sentinel(__data.size() + __d);
- }
-
- template <class _SplitBuffer>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_end(_SplitBuffer& __data) {
- __data.update_sentinel(__data.end() + 1);
- }
-};
-
-template <>
-struct __maybe_update_sentinel<false> {
- template <class _SplitBuffer, class _DifferenceType>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_size(_SplitBuffer&, _DifferenceType) {}
-
- template <class _SplitBuffer>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI static void __update_end(_SplitBuffer&) {}
-};
-
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_front(_Args&&... __args) {
@@ -687,7 +668,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// `begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
// the number of elements hasn't changed yet.
- __maybe_update_sentinel<!_Layout<__split_buffer, _Tp, _Allocator>::__is_size_based>::__update_size(*this, __d);
+ __set_size_if_size_based(__d);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, this->__alloc_);
@@ -702,7 +683,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
- __maybe_update_sentinel<_Layout<__split_buffer, _Tp, _Allocator>::__is_size_based>::__update_end(*this);
+ __set_end_if_pointer_based();
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
>From 1523be9c4ef64d32d57e5ba1bfe370de54f6cf17 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 18:01:55 +0000
Subject: [PATCH 19/28] runs clang-format
---
libcxx/include/__split_buffer | 46 +++++++++++++++++------------------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 2c315a6f46f5d..06c399e622d15 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -62,6 +62,7 @@ protected:
using const_pointer = typename __alloc_traits::const_pointer;
using iterator = pointer;
using const_iterator = const_pointer;
+
public: // TODO: make private after vector becomes size-based
pointer __first_ = nullptr;
pointer __begin_ = nullptr;
@@ -118,12 +119,9 @@ public:
__end_ = __begin_ + __new_size;
}
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type __d) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() {
- __set_sentinel(end() + 1);
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() { __set_sentinel(end() + 1); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __first_ + __new_capacity;
@@ -293,33 +291,35 @@ public:
// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows
// it to grow both in the front and back without having to move the data.
-template <class _Tp, class _Allocator = allocator<_Tp>, template <class, class, class> class _Layout = __split_buffer_pointer_layout>
+template <class _Tp,
+ class _Allocator = allocator<_Tp>,
+ template <class, class, class> class _Layout = __split_buffer_pointer_layout>
struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
using __base_type = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
- using __base_type::first;
- using __base_type::__set_first;
+ using __base_type::__back_spare;
+ using __base_type::__front_spare;
+ using __base_type::__reset;
using __base_type::__set_begin;
using __base_type::__set_capacity;
+ using __base_type::__set_end_if_pointer_based;
+ using __base_type::__set_first;
using __base_type::__set_sentinel;
using __base_type::__set_size_if_size_based;
- using __base_type::__set_end_if_pointer_based;
- using __base_type::__front_spare;
- using __base_type::__back_spare;
- using __base_type::__reset;
using __base_type::__swap_without_allocator;
+ using __base_type::first;
- using typename __base_type::value_type;
- using typename __base_type::allocator_type;
using typename __base_type::__alloc_rr;
using typename __base_type::__alloc_traits;
- using typename __base_type::reference;
+ using typename __base_type::allocator_type;
+ using typename __base_type::const_iterator;
+ using typename __base_type::const_pointer;
using typename __base_type::const_reference;
- using typename __base_type::size_type;
using typename __base_type::difference_type;
- using typename __base_type::pointer;
- using typename __base_type::const_pointer;
using typename __base_type::iterator;
- using typename __base_type::const_iterator;
+ using typename __base_type::pointer;
+ using typename __base_type::reference;
+ using typename __base_type::size_type;
+ using typename __base_type::value_type;
// A __split_buffer contains the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
@@ -362,12 +362,12 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
+ using __base_type::back;
using __base_type::begin;
+ using __base_type::capacity;
+ using __base_type::empty;
using __base_type::end;
using __base_type::size;
- using __base_type::empty;
- using __base_type::capacity;
- using __base_type::back;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(begin()); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *begin(); }
@@ -456,9 +456,7 @@ private:
__end_(__p + __n),
__parent_(__parent) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __parent_->__set_sentinel(__pos_);
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { __parent_->__set_sentinel(__pos_); }
pointer __pos_;
const pointer __end_;
>From e2c27bd756125efece69bfe9386b254ae06dfff7 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 18:24:51 +0000
Subject: [PATCH 20/28] fixes clang-tidy issues
---
libcxx/include/__split_buffer | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 06c399e622d15..f5e7e4bd0dde3 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -119,7 +119,7 @@ public:
__end_ = __begin_ + __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type __d) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() { __set_sentinel(end() + 1); }
@@ -295,7 +295,7 @@ template <class _Tp,
class _Allocator = allocator<_Tp>,
template <class, class, class> class _Layout = __split_buffer_pointer_layout>
struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
- using __base_type = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
+ using __base_type _LIBCPP_NODEBUG = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
using __base_type::__back_spare;
using __base_type::__front_spare;
using __base_type::__reset;
>From 8d1c3d92ada8d8f87a631b114297be8ea535d53f Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 19:13:22 +0000
Subject: [PATCH 21/28] more clang-tidy fixes
---
libcxx/include/__split_buffer | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index f5e7e4bd0dde3..86f602b9a836a 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -76,9 +76,9 @@ public:
_LIBCPP_HIDE_FROM_ABI explicit __split_buffer_pointer_layout(const allocator_type& __alloc)
: __alloc_(__alloc) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __first() _NOEXCEPT { return __first_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __first() const _NOEXCEPT { return __first_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
@@ -194,9 +194,9 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_size_layout(const allocator_type& __alloc)
: __alloc_(__alloc) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer first() _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __first() _NOEXCEPT { return __first_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer first() const _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __first() const _NOEXCEPT { return __first_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
@@ -297,6 +297,8 @@ template <class _Tp,
struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
using __base_type _LIBCPP_NODEBUG = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
using __base_type::__back_spare;
+ using __base_type::__copy_without_alloc;
+ using __base_type::__first;
using __base_type::__front_spare;
using __base_type::__reset;
using __base_type::__set_begin;
@@ -306,7 +308,6 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
using __base_type::__set_sentinel;
using __base_type::__set_size_if_size_based;
using __base_type::__swap_without_allocator;
- using __base_type::first;
using typename __base_type::__alloc_rr;
using typename __base_type::__alloc_traits;
@@ -416,7 +417,7 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (first() == nullptr) {
+ if (__first() == nullptr) {
if (begin() != nullptr)
return false;
@@ -428,7 +429,7 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
return true;
} else {
- if (begin() < first())
+ if (begin() < __first())
return false;
if (capacity() < size())
@@ -572,7 +573,7 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
__cap = __allocation.count;
}
- __set_begin(first() + __start);
+ __set_begin(__first() + __start);
__set_sentinel(begin());
__set_capacity(__cap);
}
@@ -580,8 +581,8 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::~__split_buffer() {
clear();
- if (first())
- __alloc_traits::deallocate(this->__alloc_, first(), capacity());
+ if (__first())
+ __alloc_traits::deallocate(this->__alloc_, __first(), capacity());
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -596,7 +597,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __base_type(__a) {
if (__a == __c.__alloc_) {
- __set_first(first());
+ __set_first(__first());
__set_begin(begin());
__set_sentinel(end());
__set_capacity(capacity());
@@ -604,8 +605,8 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, c
} else {
auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
__set_first(__allocation.ptr);
- __set_begin(first());
- __set_sentinel(this->first());
+ __set_begin(__first());
+ __set_sentinel(__first());
__set_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
>From e1a49647a12553b04027b6df9d4543bdecd9e21c Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 12 Aug 2025 21:03:38 +0000
Subject: [PATCH 22/28] fixes function calls
---
libcxx/include/__split_buffer | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 86f602b9a836a..08c3773c07b0a 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -119,9 +119,11 @@ public:
__end_ = __begin_ + __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_pointer_based(difference_type __d) {
+ __set_sentinel(size() + __d);
+ }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() { __set_sentinel(end() + 1); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_size_based() {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __first_ + __new_capacity;
@@ -236,10 +238,9 @@ public:
__size_ = __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_size_based(difference_type __d) {
- __set_sentinel(size() + __d);
- }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_pointer_based() {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_pointer_based(difference_type) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_size_based() { __set_sentinel(end() + 1); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __new_capacity;
@@ -303,10 +304,10 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
using __base_type::__reset;
using __base_type::__set_begin;
using __base_type::__set_capacity;
- using __base_type::__set_end_if_pointer_based;
+ using __base_type::__set_end_if_size_based;
using __base_type::__set_first;
using __base_type::__set_sentinel;
- using __base_type::__set_size_if_size_based;
+ using __base_type::__set_size_if_pointer_based;
using __base_type::__swap_without_allocator;
using typename __base_type::__alloc_rr;
@@ -667,7 +668,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// `begin()` was moved further into the buffer, so we need to update the pointer-based
// layout's end with it. We don't need to do anything for the size-based layout here, because
// the number of elements hasn't changed yet.
- __set_size_if_size_based(__d);
+ __set_size_if_pointer_based(__d);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, this->__alloc_);
@@ -682,7 +683,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// Now that we've added an element to the front of the buffer, we need to update the size-based
// layout's size. We don't need to do anything for the pointer-based layout here, because the end
// pointer was never updated.
- __set_end_if_pointer_based();
+ __set_end_if_size_based();
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
>From 2fd9ced5f875c5e21a540572e6400d04616b263c Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 19 Aug 2025 23:36:57 +0000
Subject: [PATCH 23/28] fixes move constructor's body
The body accidentally became synonymous with a default constructor.
---
libcxx/include/__split_buffer | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 08c3773c07b0a..a2656bbd47a5c 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -598,11 +598,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __base_type(__a) {
if (__a == __c.__alloc_) {
- __set_first(__first());
- __set_begin(begin());
- __set_sentinel(end());
- __set_capacity(capacity());
- __reset();
+ __set_first(__c.__first());
+ __set_begin(__c.begin());
+ __set_sentinel(__c.end());
+ __set_capacity(__c.capacity());
+ __c.__reset();
} else {
auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
__set_first(__allocation.ptr);
>From c736adc6ab6859e334d8182b2f631e77a873efcd Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 19 Aug 2025 23:54:42 +0000
Subject: [PATCH 24/28] reverts GDB pretty-printer change
---
libcxx/utils/gdb/libcxx/printers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index b37590dc09c3a..1c8ef6d7feb97 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -417,7 +417,7 @@ class StdDequePrinter(object):
def __init__(self, val):
self.val = val
self.size = int(val["__size_"])
- self.start_ptr = self.val["__map_"]["__data_"]["__begin_"]
+ self.start_ptr = self.val["__map_"]["__begin_"]
self.first_block_start_index = int(self.val["__start_"])
self.node_type = self.start_ptr.type
self.block_size = self._calculate_block_size(val.type.template_argument(0))
>From ec20ccc6907ff097ac013e0df71c9442421e24f1 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 20 Aug 2025 00:59:00 +0000
Subject: [PATCH 25/28] replaces `__set_begin` with `__set_valid_range`
---
libcxx/include/__split_buffer | 72 +++++++++++++++++++----------------
1 file changed, 39 insertions(+), 33 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index a2656bbd47a5c..99877f112e37c 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -102,12 +102,16 @@ public:
__first_ = __new_first;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_begin(pointer __new_begin) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
__begin_ = __new_begin;
+ __end_ = __new_end;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
+ __begin_ = __new_begin;
+ __end_ = __begin_ + __new_size;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
@@ -129,6 +133,10 @@ public:
__cap_ = __first_ + __new_capacity;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__begin_ - __first_);
+ }
+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
return static_cast<size_type>(__cap_ - __end_);
}
@@ -218,15 +226,22 @@ public:
__first_ = __new_first;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_begin(pointer __new_begin) _NOEXCEPT {
+ _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.
__size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
+ __set_sentinel(__new_end);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
+ _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.
+ __size_ -= __new_begin - __begin_;
+ __begin_ = __new_begin;
+ __set_sentinel(__new_size);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
@@ -246,6 +261,10 @@ public:
__cap_ = __new_capacity;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
+ return static_cast<size_type>(__begin_ - __first_);
+ }
+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
// `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
// the __front_spare from the count.
@@ -302,12 +321,12 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
using __base_type::__first;
using __base_type::__front_spare;
using __base_type::__reset;
- using __base_type::__set_begin;
using __base_type::__set_capacity;
using __base_type::__set_end_if_size_based;
using __base_type::__set_first;
using __base_type::__set_sentinel;
using __base_type::__set_size_if_pointer_based;
+ using __base_type::__set_valid_range;
using __base_type::__swap_without_allocator;
using typename __base_type::__alloc_rr;
@@ -341,12 +360,9 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
_LIBCPP_HIDE_FROM_ABI __split_buffer() = default;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __base_type(__a) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) : __base_type(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
: __base_type(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
@@ -544,13 +560,13 @@ __split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begi
// Updating begin at every iteration is unnecessary because destruction can't throw.
while (__begin != __new_begin)
__alloc_traits::destroy(this->__alloc_, std::__to_address(__begin++));
- __set_begin(__begin);
+ __set_valid_range(__begin, end());
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, true_type) {
- __set_begin(__new_begin);
+ __set_valid_range(__new_begin, end());
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -574,8 +590,8 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
__cap = __allocation.count;
}
- __set_begin(__first() + __start);
- __set_sentinel(begin());
+ pointer __begin = __first() + __start;
+ __set_valid_range(__begin, __begin);
__set_capacity(__cap);
}
@@ -599,15 +615,15 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, c
: __base_type(__a) {
if (__a == __c.__alloc_) {
__set_first(__c.__first());
- __set_begin(__c.begin());
- __set_sentinel(__c.end());
+ __set_valid_range(__c.begin(), __c.end());
__set_capacity(__c.capacity());
__c.__reset();
} else {
auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
__set_first(__allocation.ptr);
- __set_begin(__first());
- __set_sentinel(__first());
+
+ auto __first = this->__first();
+ __set_valid_range(__first, __first);
__set_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
@@ -663,12 +679,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
// little bit to make `emplace_front` have amortised O(1) complexity.
difference_type __d = __back_spare();
__d = (__d + 1) / 2;
- __set_begin(std::move_backward(begin(), __end, __end + __d));
-
- // `begin()` was moved further into the buffer, so we need to update the pointer-based
- // layout's end with it. We don't need to do anything for the size-based layout here, because
- // the number of elements hasn't changed yet.
- __set_size_if_pointer_based(__d);
+ auto __new_end = __end + __d;
+ __set_valid_range(std::move_backward(begin(), __end, __new_end), __new_end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, this->__alloc_);
@@ -678,12 +690,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
}
__alloc_traits::construct(this->__alloc_, std::__to_address(begin() - 1), std::forward<_Args>(__args)...);
- __set_begin(begin() - 1);
-
- // Now that we've added an element to the front of the buffer, we need to update the size-based
- // layout's size. We don't need to do anything for the pointer-based layout here, because the end
- // pointer was never updated.
- __set_end_if_size_based();
+ __set_valid_range(begin() - 1, size() + 1);
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -695,8 +702,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
difference_type __d = __front_spare();
__d = (__d + 1) / 2;
__end = std::move(begin(), __end, begin() - __d);
- __set_begin(begin() - __d);
- __set_sentinel(__end);
+ __set_valid_range(begin() - __d, __end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, this->__alloc_);
>From a5ef31f0096711eb5d54894ef90c90f970151d0b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 20 Aug 2025 04:21:40 +0000
Subject: [PATCH 26/28] renames `__first_` to `__data_` to avoid shadow
warnings
---
libcxx/include/__split_buffer | 82 +++++++++++++-------------------
libcxx/include/__vector/vector.h | 8 ++--
2 files changed, 38 insertions(+), 52 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 99877f112e37c..3bcf91dd40cc0 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -64,7 +64,7 @@ protected:
using const_iterator = const_pointer;
public: // TODO: make private after vector becomes size-based
- pointer __first_ = nullptr;
+ pointer __data_ = nullptr;
pointer __begin_ = nullptr;
pointer __end_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
@@ -76,9 +76,9 @@ public:
_LIBCPP_HIDE_FROM_ABI explicit __split_buffer_pointer_layout(const allocator_type& __alloc)
: __alloc_(__alloc) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __first() _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __data() _NOEXCEPT { return __data_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __first() const _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __data() const _NOEXCEPT { return __data_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
@@ -95,11 +95,11 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __begin_ == __end_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __first_);
+ return static_cast<size_type>(__cap_ - __data_);
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_first(pointer __new_first) _NOEXCEPT {
- __first_ = __new_first;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_data(pointer __new_first) _NOEXCEPT {
+ __data_ = __new_first;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
@@ -115,7 +115,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
- _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ _LIBCPP_ASSERT_INTERNAL(__data_ <= __new_end, "__new_end cannot precede __data_");
__end_ = __new_end;
}
@@ -123,18 +123,12 @@ public:
__end_ = __begin_ + __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_pointer_based(difference_type __d) {
- __set_sentinel(size() + __d);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_size_based() {}
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
- __cap_ = __first_ + __new_capacity;
+ __cap_ = __data_ + __new_capacity;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
+ return static_cast<size_type>(__begin_ - __data_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
@@ -147,7 +141,7 @@ public:
template <class _OtherLayout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_OtherLayout& __other) _NOEXCEPT {
- std::swap(__first_, __other.__first_);
+ std::swap(__data_, __other.__data_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
std::swap(__end_, __other.__end_);
@@ -159,7 +153,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __first_ = nullptr;
+ __data_ = nullptr;
__begin_ = nullptr;
__end_ = nullptr;
__cap_ = nullptr;
@@ -168,7 +162,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__copy_without_alloc(__split_buffer_pointer_layout const& __other)
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __first_ = __other.__first_;
+ __data_ = __other.__data_;
__begin_ = __other.__begin_;
__cap_ = __other.__cap_;
__end_ = __other.__end_;
@@ -192,7 +186,7 @@ protected:
using const_iterator = const_pointer;
public: // TODO: make private after vector becomes size-based
- pointer __first_ = nullptr;
+ pointer __data_ = nullptr;
pointer __begin_ = nullptr;
size_type __size_ = 0;
size_type __cap_ = 0;
@@ -204,9 +198,9 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_size_layout(const allocator_type& __alloc)
: __alloc_(__alloc) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __first() _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __data() _NOEXCEPT { return __data_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __first() const _NOEXCEPT { return __first_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __data() const _NOEXCEPT { return __data_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
@@ -222,8 +216,8 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_first(pointer __new_first) _NOEXCEPT {
- __first_ = __new_first;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_data(pointer __new_first) _NOEXCEPT {
+ __data_ = __new_first;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
@@ -245,7 +239,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
- _LIBCPP_ASSERT_INTERNAL(__first_ <= __new_end, "__new_end cannot precede __first_");
+ _LIBCPP_ASSERT_INTERNAL(__data_ <= __new_end, "__new_end cannot precede __data_");
__size_ += __new_end - end();
}
@@ -253,16 +247,12 @@ public:
__size_ = __new_size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_size_if_pointer_based(difference_type) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_end_if_size_based() { __set_sentinel(end() + 1); }
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
__cap_ = __new_capacity;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
- return static_cast<size_type>(__begin_ - __first_);
+ return static_cast<size_type>(__begin_ - __data_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
@@ -279,7 +269,7 @@ public:
template <class _Data2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(_Data2& __other) _NOEXCEPT {
- std::swap(__first_, __other.__first_);
+ std::swap(__data_, __other.__data_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
std::swap(__size_, __other.__size_);
@@ -291,7 +281,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __first_ = nullptr;
+ __data_ = nullptr;
__begin_ = nullptr;
__size_ = 0;
__cap_ = 0;
@@ -300,7 +290,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__copy_without_alloc(__split_buffer_size_layout const& __other)
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __first_ = __other.__first_;
+ __data_ = __other.__data_;
__begin_ = __other.__begin_;
__cap_ = __other.__cap_;
__size_ = __other.__size_;
@@ -308,7 +298,7 @@ public:
};
// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_).
-// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows
+// It has uninitialized memory in the ranges [__data_, __begin_) and [__end_, __cap_). That allows
// it to grow both in the front and back without having to move the data.
template <class _Tp,
@@ -318,14 +308,12 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
using __base_type _LIBCPP_NODEBUG = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
using __base_type::__back_spare;
using __base_type::__copy_without_alloc;
- using __base_type::__first;
+ using __base_type::__data;
using __base_type::__front_spare;
using __base_type::__reset;
using __base_type::__set_capacity;
- using __base_type::__set_end_if_size_based;
- using __base_type::__set_first;
+ using __base_type::__set_data;
using __base_type::__set_sentinel;
- using __base_type::__set_size_if_pointer_based;
using __base_type::__set_valid_range;
using __base_type::__swap_without_allocator;
@@ -434,7 +422,7 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__first() == nullptr) {
+ if (__data() == nullptr) {
if (begin() != nullptr)
return false;
@@ -446,7 +434,7 @@ struct __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _
return true;
} else {
- if (begin() < __first())
+ if (begin() < __data())
return false;
if (capacity() < size())
@@ -586,11 +574,11 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
auto __allocation = std::__allocate_at_least(this->__alloc_, __cap);
- __set_first(__allocation.ptr);
+ __set_data(__allocation.ptr);
__cap = __allocation.count;
}
- pointer __begin = __first() + __start;
+ pointer __begin = __data() + __start;
__set_valid_range(__begin, __begin);
__set_capacity(__cap);
}
@@ -598,8 +586,8 @@ __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_t
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::~__split_buffer() {
clear();
- if (__first())
- __alloc_traits::deallocate(this->__alloc_, __first(), capacity());
+ if (__data())
+ __alloc_traits::deallocate(this->__alloc_, __data(), capacity());
}
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
@@ -614,16 +602,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
: __base_type(__a) {
if (__a == __c.__alloc_) {
- __set_first(__c.__first());
+ __set_data(__c.__data());
__set_valid_range(__c.begin(), __c.end());
__set_capacity(__c.capacity());
__c.__reset();
} else {
auto __allocation = std::__allocate_at_least(this->__alloc_, __c.size());
- __set_first(__allocation.ptr);
-
- auto __first = this->__first();
- __set_valid_range(__first, __first);
+ __set_data(__allocation.ptr);
+ __set_valid_range(__data(), __data());
__set_capacity(__allocation.count);
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 31ac508c2f087..e69ac656b8305 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -853,13 +853,13 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
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));
- __v.__begin_ = __new_begin;
+ __v.__set_valid_range(__new_begin, __v.end());
__end_ = __begin_; // All the objects have been destroyed by relocating them.
std::swap(this->__begin_, __v.__begin_);
std::swap(this->__end_, __v.__end_);
std::swap(this->__cap_, __v.__cap_);
- __v.__set_first(__v.begin());
+ __v.__set_data(__v.begin());
__annotate_new(size());
}
@@ -884,12 +884,12 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
std::__uninitialized_allocator_relocate(
this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__begin_ = __new_begin;
+ __v.__set_valid_range(__new_begin, __v.end());
__end_ = __begin_; // All the objects have been destroyed by relocating them.
std::swap(this->__begin_, __v.__begin_);
std::swap(this->__end_, __v.__end_);
std::swap(this->__cap_, __v.__cap_);
- __v.__first_ = __v.begin();
+ __v.__set_data(__v.begin());
__annotate_new(size());
return __ret;
}
>From 971559b40ad677e76a19c9cb57dc026d885d4b5a Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 20 Aug 2025 16:41:49 +0000
Subject: [PATCH 27/28] applies clang-format
---
libcxx/include/__split_buffer | 12 ++++++------
libcxx/include/__vector/vector.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 3bcf91dd40cc0..edde9c370935e 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -64,7 +64,7 @@ protected:
using const_iterator = const_pointer;
public: // TODO: make private after vector becomes size-based
- pointer __data_ = nullptr;
+ pointer __data_ = nullptr;
pointer __begin_ = nullptr;
pointer __end_ = nullptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
@@ -153,7 +153,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __data_ = nullptr;
+ __data_ = nullptr;
__begin_ = nullptr;
__end_ = nullptr;
__cap_ = nullptr;
@@ -162,7 +162,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__copy_without_alloc(__split_buffer_pointer_layout const& __other)
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __data_ = __other.__data_;
+ __data_ = __other.__data_;
__begin_ = __other.__begin_;
__cap_ = __other.__cap_;
__end_ = __other.__end_;
@@ -186,7 +186,7 @@ protected:
using const_iterator = const_pointer;
public: // TODO: make private after vector becomes size-based
- pointer __data_ = nullptr;
+ pointer __data_ = nullptr;
pointer __begin_ = nullptr;
size_type __size_ = 0;
size_type __cap_ = 0;
@@ -281,7 +281,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
- __data_ = nullptr;
+ __data_ = nullptr;
__begin_ = nullptr;
__size_ = 0;
__cap_ = 0;
@@ -290,7 +290,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__copy_without_alloc(__split_buffer_size_layout const& __other)
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
- __data_ = __other.__data_;
+ __data_ = __other.__data_;
__begin_ = __other.__begin_;
__cap_ = __other.__cap_;
__size_ = __other.__size_;
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index e69ac656b8305..7f876db4fd224 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -885,7 +885,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
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.
+ __end_ = __begin_; // All the objects have been destroyed by relocating them.
std::swap(this->__begin_, __v.__begin_);
std::swap(this->__end_, __v.__end_);
std::swap(this->__cap_, __v.__cap_);
>From 895b546a631807c512db2926bc45ff9500bc217b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 20 Aug 2025 20:56:12 +0000
Subject: [PATCH 28/28] fixes LLDB issue
---
lldb/examples/synthetic/libcxx.py | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py
index e2932d8f54019..c24820f42ec26 100644
--- a/lldb/examples/synthetic/libcxx.py
+++ b/lldb/examples/synthetic/libcxx.py
@@ -77,15 +77,6 @@ def stdstring_SummaryProvider(valobj, dict):
return '"' + strval + '"'
-def get_buffer_data(parent):
- map_valobj = parent.valobj.GetChildMemberWithName("__map_")
- map_data = map_valobj.GetChildMemberWithName("__data_")
- if map_data.IsValid():
- return map_data
-
- return map_valobj
-
-
def get_buffer_end(buffer, begin):
"""
Returns a pointer to where the next element would be pushed.
@@ -808,7 +799,7 @@ def update(self):
return
start = self.valobj.GetChildMemberWithName("__start_").GetValueAsUnsigned(0)
- map_ = get_buffer_data(self)
+ map_ = self.valobj.GetChildMemberWithName("__map_")
is_size_based = map_.GetChildMemberWithName("__size_").IsValid()
first = map_.GetChildMemberWithName("__first_")
map_first = first.GetValueAsUnsigned(0)
More information about the libcxx-commits
mailing list