[libcxx-commits] [libcxx] [libc++] Replace `__compressed_pair` with `[[no_unique_address]]` (PR #76756)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jun 24 12:28:18 PDT 2024
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/76756
>From 9f7a8778eb4eaf1c82848d57049b486f6a88d8c1 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 1 Jan 2024 18:47:45 +0100
Subject: [PATCH] [libc++] Replace `__compressed_pair` with
`[[no_unique_address]]`
---
libcxx/docs/ReleaseNotes/19.rst | 3 +
libcxx/docs/ReleaseNotes/20.rst | 77 +++++++
libcxx/include/__config | 1 +
libcxx/include/__configuration/abi.h | 7 +
libcxx/include/__functional/function.h | 27 +--
libcxx/include/__hash_table | 155 ++++++++------
libcxx/include/__memory/compressed_pair.h | 200 ++++++------------
libcxx/include/__memory/shared_ptr.h | 44 ++--
libcxx/include/__memory/unique_ptr.h | 124 ++++++-----
libcxx/include/__split_buffer | 27 ++-
libcxx/include/__tree | 53 ++---
libcxx/include/__type_traits/datasizeof.h | 4 +
libcxx/include/deque | 45 ++--
libcxx/include/forward_list | 21 +-
libcxx/include/future | 22 +-
libcxx/include/list | 21 +-
libcxx/include/string | 147 +++++++------
libcxx/include/vector | 89 ++++----
.../missing_hash_specialization.verify.cpp | 9 +-
.../compressed_pair/compressed_pair.pass.cpp | 52 -----
.../libcxx.control_block_layout.pass.cpp | 113 +++++++---
21 files changed, 645 insertions(+), 596 deletions(-)
create mode 100644 libcxx/docs/ReleaseNotes/20.rst
delete mode 100644 libcxx/test/libcxx/memory/compressed_pair/compressed_pair.pass.cpp
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 71de10abb6eaa..e355893edc90a 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -143,6 +143,9 @@ ABI Affecting Changes
``random_device`` could throw a ``system_error`` with this value. It now
throws ``ENOMSG``.
+- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``. This change results in
+ empty final types being placed at the beginning of the object instead of where the beginning of the
+ ``__compressed_pair`` subobject was. This is only observable by checking the address of the subobject.
Build System Changes
--------------------
diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
new file mode 100644
index 0000000000000..93b19df8cd167
--- /dev/null
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -0,0 +1,77 @@
+===========================================
+Libc++ 20.0.0 (In-Progress) Release Notes
+===========================================
+
+.. contents::
+ :local:
+ :depth: 2
+
+Written by the `Libc++ Team <https://libcxx.llvm.org>`_
+
+.. warning::
+
+ These are in-progress notes for the upcoming libc++ 20.0.0 release.
+ Release notes for previous releases can be found on
+ `the Download Page <https://releases.llvm.org/download.html>`_.
+
+Introduction
+============
+
+This document contains the release notes for the libc++ C++ Standard Library,
+part of the LLVM Compiler Infrastructure, release 19.0.0. Here we describe the
+status of libc++ in some detail, including major improvements from the previous
+release and new feature work. For the general LLVM release notes, see `the LLVM
+documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM releases may
+be downloaded from the `LLVM releases web site <https://llvm.org/releases/>`_.
+
+For more information about libc++, please see the `Libc++ Web Site
+<https://libcxx.llvm.org>`_ or the `LLVM Web Site <https://llvm.org>`_.
+
+Note that if you are reading this file from a Git checkout or the
+main Libc++ web page, this document applies to the *next* release, not
+the current one. To see the release notes for a specific release, please
+see the `releases page <https://llvm.org/releases/>`_.
+
+What's New in Libc++ 20.0.0?
+==============================
+
+Implemented Papers
+------------------
+
+Improvements and New Features
+-----------------------------
+
+- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``, resulting in reduced
+ compile times and smaller debug information as well as better code gen if optimizations are disabled.
+
+Deprecations and Removals
+-------------------------
+
+- TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable and the ``_LIBCPP_ENABLE_ASSERTIONS`` macro that were used to
+ enable the safe mode will be removed in LLVM 20.
+
+Upcoming Deprecations and Removals
+----------------------------------
+
+LLVM 21
+~~~~~~~
+TODO
+
+
+ABI Affecting Changes
+---------------------
+
+- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``. This change results in
+ empty final types being placed at the beginning of the object instead of where the beginning of the
+ ``__compressed_pair`` subobject was. This is only observable by checking the address of the subobject.
+
+Build System Changes
+--------------------
+
+- The ``LIBCXX_EXECUTOR`` and ``LIBCXXABI_EXECUTOR`` CMake variables have been removed. Please
+ set ``LIBCXX_TEST_PARAMS`` to ``executor=<...>`` instead.
+
+- The Cmake variable ``LIBCXX_ENABLE_CLANG_TIDY`` has been removed. The build system has been changed
+ to automatically detect the presence of ``clang-tidy`` and the required ``Clang`` libraries.
+
+- The CMake options ``LIBCXX_INSTALL_MODULES`` now defaults to ``ON``.
diff --git a/libcxx/include/__config b/libcxx/include/__config
index dfb14fd6a380c..54d0d1addeeb0 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -31,6 +31,7 @@
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
+# define _LIBCPP_CONCAT3(X, Y, Z) _LIBCPP_CONCAT(X, _LIBCPP_CONCAT(Y, Z))
# if __STDC_HOSTED__ == 0
# define _LIBCPP_FREESTANDING
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 513da6e3b81b6..f4e57ba67e486 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -91,6 +91,13 @@
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
// Dont' add an inline namespace for `std::filesystem`
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
+// Historically, libc++ used a type called `__compressed_pair` to reduce storage need in cases of empty types (e.g. an
+// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons
+// we had to add artificial padding in a few places.
+//
+// This setting disables the addition of such artificial padding, leading to a more optimal
+// representation for several types.
+# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
#elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index c7b98035e34bf..b073af4f64ab5 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -143,45 +143,46 @@ class __default_alloc_func;
template <class _Fp, class _Ap, class _Rp, class... _ArgTypes>
class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
- __compressed_pair<_Fp, _Ap> __f_;
+ _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_);
public:
typedef _LIBCPP_NODEBUG _Fp _Target;
typedef _LIBCPP_NODEBUG _Ap _Alloc;
- _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_.first(); }
+ _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __func_; }
// WIN32 APIs may define __allocator, so use __get_allocator instead.
- _LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __f_.second(); }
+ _LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __alloc_; }
- _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f)
- : __f_(piecewise_construct, std::forward_as_tuple(std::move(__f)), std::forward_as_tuple()) {}
+ _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f) : __func_(std::move(__f)), __alloc_() {}
- _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a)
- : __f_(piecewise_construct, std::forward_as_tuple(__f), std::forward_as_tuple(__a)) {}
+ _LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {}
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, _Alloc&& __a)
- : __f_(piecewise_construct, std::forward_as_tuple(__f), std::forward_as_tuple(std::move(__a))) {}
+ : __func_(__f), __alloc_(std::move(__a)) {}
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a)
- : __f_(piecewise_construct, std::forward_as_tuple(std::move(__f)), std::forward_as_tuple(std::move(__a))) {}
+ : __func_(std::move(__f)), __alloc_(std::move(__a)) {}
_LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(__f_.first(), std::forward<_ArgTypes>(__arg)...);
+ return _Invoker::__call(__func_, std::forward<_ArgTypes>(__arg)...);
}
_LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const {
typedef allocator_traits<_Alloc> __alloc_traits;
typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA;
- _AA __a(__f_.second());
+ _AA __a(__alloc_);
typedef __allocator_destructor<_AA> _Dp;
unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
- ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a));
+ ::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a));
return __hold.release();
}
- _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); }
+ _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT {
+ __func_.~_Fp();
+ __alloc_.~_Alloc();
+ }
_LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) {
typedef allocator_traits<_Alloc> __alloc_traits;
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 025758528573f..10a7ceec6c412 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -554,29 +554,29 @@ class __bucket_list_deallocator {
typedef allocator_traits<allocator_type> __alloc_traits;
typedef typename __alloc_traits::size_type size_type;
- __compressed_pair<size_type, allocator_type> __data_;
+ _LIBCPP_COMPRESSED_PAIR(size_type, __size_, allocator_type, __alloc_);
public:
typedef typename __alloc_traits::pointer pointer;
_LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __data_(0, __default_init_tag()) {}
+ : __size_(0) {}
_LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(const allocator_type& __a, size_type __size)
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __data_(__size, __a) {}
+ : __size_(__size), __alloc_(__a) {}
_LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(__bucket_list_deallocator&& __x)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __data_(std::move(__x.__data_)) {
+ : __size_(std::move(__x.__size_)), __alloc_(std::move(__x.__alloc_)) {
__x.size() = 0;
}
- _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __data_.first(); }
- _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __data_.first(); }
+ _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __size_; }
+ _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
- _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __data_.second(); }
- _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __data_.second(); }
+ _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __alloc_; }
+ _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __alloc_; }
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { __alloc_traits::deallocate(__alloc(), __p, size()); }
};
@@ -716,27 +716,27 @@ private:
// --- Member data begin ---
__bucket_list __bucket_list_;
- __compressed_pair<__first_node, __node_allocator> __p1_;
- __compressed_pair<size_type, hasher> __p2_;
- __compressed_pair<float, key_equal> __p3_;
+ _LIBCPP_COMPRESSED_PAIR(__first_node, __first_node_, __node_allocator, __node_alloc_);
+ _LIBCPP_COMPRESSED_PAIR(size_type, __size_, hasher, __hasher_);
+ _LIBCPP_COMPRESSED_PAIR(float, __max_load_factor_, key_equal, __key_eq_);
// --- Member data end ---
- _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __p2_.first(); }
+ _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __size_; }
public:
- _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __p2_.first(); }
+ _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
- _LIBCPP_HIDE_FROM_ABI hasher& hash_function() _NOEXCEPT { return __p2_.second(); }
- _LIBCPP_HIDE_FROM_ABI const hasher& hash_function() const _NOEXCEPT { return __p2_.second(); }
+ _LIBCPP_HIDE_FROM_ABI hasher& hash_function() _NOEXCEPT { return __hasher_; }
+ _LIBCPP_HIDE_FROM_ABI const hasher& hash_function() const _NOEXCEPT { return __hasher_; }
- _LIBCPP_HIDE_FROM_ABI float& max_load_factor() _NOEXCEPT { return __p3_.first(); }
- _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __p3_.first(); }
+ _LIBCPP_HIDE_FROM_ABI float& max_load_factor() _NOEXCEPT { return __max_load_factor_; }
+ _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __max_load_factor_; }
- _LIBCPP_HIDE_FROM_ABI key_equal& key_eq() _NOEXCEPT { return __p3_.second(); }
- _LIBCPP_HIDE_FROM_ABI const key_equal& key_eq() const _NOEXCEPT { return __p3_.second(); }
+ _LIBCPP_HIDE_FROM_ABI key_equal& key_eq() _NOEXCEPT { return __key_eq_; }
+ _LIBCPP_HIDE_FROM_ABI const key_equal& key_eq() const _NOEXCEPT { return __key_eq_; }
- _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __p1_.second(); }
- _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __p1_.second(); }
+ _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; }
+ _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; }
public:
typedef __hash_iterator<__node_pointer> iterator;
@@ -1022,26 +1022,34 @@ inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() _NOEXCEPT_(
is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
is_nothrow_default_constructible<key_equal>::value)
- : __p2_(0, __default_init_tag()), __p3_(1.0f, __default_init_tag()) {}
+ : __size_(0), __max_load_factor_(1.0f) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql)
- : __bucket_list_(nullptr, __bucket_list_deleter()), __p1_(), __p2_(0, __hf), __p3_(1.0f, __eql) {}
+ : __bucket_list_(nullptr, __bucket_list_deleter()),
+ __first_node_(),
+ __node_alloc_(),
+ __size_(0),
+ __hasher_(__hf),
+ __max_load_factor_(1.0f),
+ __key_eq_(__eql) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(
const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
- __p1_(__default_init_tag(), __node_allocator(__a)),
- __p2_(0, __hf),
- __p3_(1.0f, __eql) {}
+ __node_alloc_(__node_allocator(__a)),
+ __size_(0),
+ __hasher_(__hf),
+ __max_load_factor_(1.0f),
+ __key_eq_(__eql) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
- __p1_(__default_init_tag(), __node_allocator(__a)),
- __p2_(0, __default_init_tag()),
- __p3_(1.0f, __default_init_tag()) {}
+ __node_alloc_(__node_allocator(__a)),
+ __size_(0),
+ __max_load_factor_(1.0f) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
@@ -1049,17 +1057,20 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
__bucket_list_deleter(allocator_traits<__pointer_allocator>::select_on_container_copy_construction(
__u.__bucket_list_.get_deleter().__alloc()),
0)),
- __p1_(__default_init_tag(),
- allocator_traits<__node_allocator>::select_on_container_copy_construction(__u.__node_alloc())),
- __p2_(0, __u.hash_function()),
- __p3_(__u.__p3_) {}
+ __node_alloc_(allocator_traits<__node_allocator>::select_on_container_copy_construction(__u.__node_alloc())),
+ __size_(0),
+ __hasher_(__u.hash_function()),
+ __max_load_factor_(__u.__max_load_factor_),
+ __key_eq_(__u.__key_eq_) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, const allocator_type& __a)
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
- __p1_(__default_init_tag(), __node_allocator(__a)),
- __p2_(0, __u.hash_function()),
- __p3_(__u.__p3_) {}
+ __node_alloc_(__node_allocator(__a)),
+ __size_(0),
+ __hasher_(__u.hash_function()),
+ __max_load_factor_(__u.__max_load_factor_),
+ __key_eq_(__u.__key_eq_) {}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEXCEPT_(
@@ -1067,12 +1078,15 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEX
is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
is_nothrow_move_constructible<key_equal>::value)
: __bucket_list_(std::move(__u.__bucket_list_)),
- __p1_(std::move(__u.__p1_)),
- __p2_(std::move(__u.__p2_)),
- __p3_(std::move(__u.__p3_)) {
+ __first_node_(std::move(__u.__first_node_)),
+ __node_alloc_(std::move(__u.__node_alloc_)),
+ __size_(std::move(__u.__size_)),
+ __hasher_(std::move(__u.__hasher_)),
+ __max_load_factor_(__u.__max_load_factor_),
+ __key_eq_(std::move(__u.__key_eq_)) {
if (size() > 0) {
- __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
- __u.__p1_.first().__next_ = nullptr;
+ __bucket_list_[std::__constrain_hash(__first_node_.__next_->__hash(), bucket_count())] = __first_node_.__ptr();
+ __u.__first_node_.__next_ = nullptr;
__u.size() = 0;
}
}
@@ -1080,17 +1094,19 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEX
template <class _Tp, class _Hash, class _Equal, class _Alloc>
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const allocator_type& __a)
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
- __p1_(__default_init_tag(), __node_allocator(__a)),
- __p2_(0, std::move(__u.hash_function())),
- __p3_(std::move(__u.__p3_)) {
+ __node_alloc_(__node_allocator(__a)),
+ __size_(0),
+ __hasher_(std::move(__u.__hasher_)),
+ __max_load_factor_(__u.__max_load_factor_),
+ __key_eq_(std::move(__u.__key_eq_)) {
if (__a == allocator_type(__u.__node_alloc())) {
__bucket_list_.reset(__u.__bucket_list_.release());
__bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
__u.__bucket_list_.get_deleter().size() = 0;
if (__u.size() > 0) {
- __p1_.first().__next_ = __u.__p1_.first().__next_;
- __u.__p1_.first().__next_ = nullptr;
- __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
+ __first_node_.__next_ = __u.__first_node_.__next_;
+ __u.__first_node_.__next_ = nullptr;
+ __bucket_list_[std::__constrain_hash(__first_node_.__next_->__hash(), bucket_count())] = __first_node_.__ptr();
size() = __u.size();
__u.size() = 0;
}
@@ -1104,7 +1120,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
static_assert(is_copy_constructible<hasher>::value, "Hasher must be copy-constructible.");
#endif
- __deallocate_node(__p1_.first().__next_);
+ __deallocate_node(__first_node_.__next_);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
@@ -1150,8 +1166,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
for (size_type __i = 0; __i < __bc; ++__i)
__bucket_list_[__i] = nullptr;
size() = 0;
- __next_pointer __cache = __p1_.first().__next_;
- __p1_.first().__next_ = nullptr;
+ __next_pointer __cache = __first_node_.__next_;
+ __first_node_.__next_ = nullptr;
return __cache;
}
@@ -1168,10 +1184,10 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u,
hash_function() = std::move(__u.hash_function());
max_load_factor() = __u.max_load_factor();
key_eq() = std::move(__u.key_eq());
- __p1_.first().__next_ = __u.__p1_.first().__next_;
+ __first_node_.__next_ = __u.__first_node_.__next_;
if (size() > 0) {
- __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
- __u.__p1_.first().__next_ = nullptr;
+ __bucket_list_[std::__constrain_hash(__first_node_.__next_->__hash(), bucket_count())] = __first_node_.__ptr();
+ __u.__first_node_.__next_ = nullptr;
__u.size() = 0;
}
}
@@ -1288,7 +1304,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f
template <class _Tp, class _Hash, class _Equal, class _Alloc>
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT {
- return iterator(__p1_.first().__next_);
+ return iterator(__first_node_.__next_);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
@@ -1300,7 +1316,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT {
template <class _Tp, class _Hash, class _Equal, class _Alloc>
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT {
- return const_iterator(__p1_.first().__next_);
+ return const_iterator(__first_node_.__next_);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
@@ -1312,8 +1328,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
template <class _Tp, class _Hash, class _Equal, class _Alloc>
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT {
if (size() > 0) {
- __deallocate_node(__p1_.first().__next_);
- __p1_.first().__next_ = nullptr;
+ __deallocate_node(__first_node_.__next_);
+ __first_node_.__next_ = nullptr;
size_type __bc = bucket_count();
for (size_type __i = 0; __i < __bc; ++__i)
__bucket_list_[__i] = nullptr;
@@ -1365,7 +1381,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(__node_po
// insert_after __bucket_list_[__chash], or __first_node if bucket is null
__next_pointer __pn = __bucket_list_[__chash];
if (__pn == nullptr) {
- __pn = __p1_.first().__ptr();
+ __pn = __first_node_.__ptr();
__nd->__next_ = __pn->__next_;
__pn->__next_ = __nd->__ptr();
// fix up __bucket_list_
@@ -1445,7 +1461,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
size_type __bc = bucket_count();
size_t __chash = std::__constrain_hash(__cp->__hash_, __bc);
if (__pn == nullptr) {
- __pn = __p1_.first().__ptr();
+ __pn = __first_node_.__ptr();
__cp->__next_ = __pn->__next_;
__pn->__next_ = __cp->__ptr();
// fix up __bucket_list_
@@ -1530,7 +1546,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const&
// insert_after __bucket_list_[__chash], or __first_node if bucket is null
__next_pointer __pn = __bucket_list_[__chash];
if (__pn == nullptr) {
- __pn = __p1_.first().__ptr();
+ __pn = __first_node_.__ptr();
__h->__next_ = __pn->__next_;
__pn->__next_ = __h.get()->__ptr();
// fix up __bucket_list_
@@ -1708,7 +1724,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) {
if (__nbc > 0) {
for (size_type __i = 0; __i < __nbc; ++__i)
__bucket_list_[__i] = nullptr;
- __next_pointer __pp = __p1_.first().__ptr();
+ __next_pointer __pp = __first_node_.__ptr();
__next_pointer __cp = __pp->__next_;
if (__cp != nullptr) {
size_type __chash = std::__constrain_hash(__cp->__hash(), __nbc);
@@ -1885,7 +1901,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT {
// Fix up __bucket_list_
// if __pn is not in same bucket (before begin is not in same bucket) &&
// if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
- if (__pn == __p1_.first().__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
+ if (__pn == __first_node_.__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
if (__cn->__next_ == nullptr || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
__bucket_list_[__chash] = nullptr;
}
@@ -2004,14 +2020,17 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
std::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
std::__swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc());
std::__swap_allocator(__node_alloc(), __u.__node_alloc());
- std::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
- __p2_.swap(__u.__p2_);
- __p3_.swap(__u.__p3_);
+ std::swap(__first_node_.__next_, __u.__first_node_.__next_);
+ using std::swap;
+ swap(__size_, __u.__size_);
+ swap(__hasher_, __u.__hasher_);
+ swap(__max_load_factor_, __u.__max_load_factor_);
+ swap(__key_eq_, __u.__key_eq_);
if (size() > 0)
- __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
+ __bucket_list_[std::__constrain_hash(__first_node_.__next_->__hash(), bucket_count())] = __first_node_.__ptr();
if (__u.size() > 0)
- __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
- __u.__p1_.first().__ptr();
+ __u.__bucket_list_[std::__constrain_hash(__u.__first_node_.__next_->__hash(), __u.bucket_count())] =
+ __u.__first_node_.__ptr();
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h
index 40e5cfc35fb04..3a6947dab4b59 100644
--- a/libcxx/include/__memory/compressed_pair.h
+++ b/libcxx/include/__memory/compressed_pair.h
@@ -11,161 +11,79 @@
#define _LIBCPP___MEMORY_COMPRESSED_PAIR_H
#include <__config>
-#include <__fwd/tuple.h>
-#include <__tuple/tuple_indices.h>
-#include <__type_traits/decay.h>
-#include <__type_traits/dependent_type.h>
-#include <__type_traits/enable_if.h>
-#include <__type_traits/is_constructible.h>
+#include <__type_traits/datasizeof.h>
#include <__type_traits/is_empty.h>
#include <__type_traits/is_final.h>
-#include <__type_traits/is_same.h>
-#include <__type_traits/is_swappable.h>
-#include <__utility/forward.h>
-#include <__utility/move.h>
-#include <__utility/piecewise_construct.h>
-#include <cstddef>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
_LIBCPP_BEGIN_NAMESPACE_STD
-// Tag used to default initialize one or both of the pair's elements.
-struct __default_init_tag {};
-struct __value_init_tag {};
-
-template <class _Tp, int _Idx, bool _CanBeEmptyBase = is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value>
-struct __compressed_pair_elem {
- using _ParamT = _Tp;
- using reference = _Tp&;
- using const_reference = const _Tp&;
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_() {}
-
- template <class _Up, __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u)
- : __value_(std::forward<_Up>(__u)) {}
-
-#ifndef _LIBCPP_CXX03_LANG
- template <class... _Args, size_t... _Indices>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit __compressed_pair_elem(
- piecewise_construct_t, tuple<_Args...> __args, __tuple_indices<_Indices...>)
- : __value_(std::forward<_Args>(std::get<_Indices>(__args))...) {}
-#endif
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference __get() _NOEXCEPT { return __value_; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const_reference __get() const _NOEXCEPT { return __value_; }
-
-private:
- _Tp __value_;
-};
-
-template <class _Tp, int _Idx>
-struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {
- using _ParamT = _Tp;
- using reference = _Tp&;
- using const_reference = const _Tp&;
- using __value_type = _Tp;
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem() = default;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_type() {}
-
- template <class _Up, __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u)
- : __value_type(std::forward<_Up>(__u)) {}
-
-#ifndef _LIBCPP_CXX03_LANG
- template <class... _Args, size_t... _Indices>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
- __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, __tuple_indices<_Indices...>)
- : __value_type(std::forward<_Args>(std::get<_Indices>(__args))...) {}
-#endif
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference __get() _NOEXCEPT { return *this; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const_reference __get() const _NOEXCEPT { return *this; }
-};
-
-template <class _T1, class _T2>
-class __compressed_pair : private __compressed_pair_elem<_T1, 0>, private __compressed_pair_elem<_T2, 1> {
-public:
- // NOTE: This static assert should never fire because __compressed_pair
- // is *almost never* used in a scenario where it's possible for T1 == T2.
- // (The exception is std::function where it is possible that the function
- // object and the allocator have the same type).
- static_assert(
- (!is_same<_T1, _T2>::value),
- "__compressed_pair cannot be instantiated when T1 and T2 are the same type; "
- "The current implementation is NOT ABI-compatible with the previous implementation for this configuration");
-
- using _Base1 _LIBCPP_NODEBUG = __compressed_pair_elem<_T1, 0>;
- using _Base2 _LIBCPP_NODEBUG = __compressed_pair_elem<_T2, 1>;
-
- template <bool _Dummy = true,
- __enable_if_t< __dependent_type<is_default_constructible<_T1>, _Dummy>::value &&
- __dependent_type<is_default_constructible<_T2>, _Dummy>::value,
- int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair()
- : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {}
-
- template <class _U1, class _U2>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair(_U1&& __t1, _U2&& __t2)
- : _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {}
-
-#ifndef _LIBCPP_CXX03_LANG
- template <class... _Args1, class... _Args2>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit __compressed_pair(
- piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args)
- : _Base1(__pc, std::move(__first_args), typename __make_tuple_indices<sizeof...(_Args1)>::type()),
- _Base2(__pc, std::move(__second_args), typename __make_tuple_indices<sizeof...(_Args2)>::type()) {}
-#endif
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename _Base1::reference first() _NOEXCEPT {
- return static_cast<_Base1&>(*this).__get();
- }
+#ifndef _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename _Base1::const_reference first() const _NOEXCEPT {
- return static_cast<_Base1 const&>(*this).__get();
- }
+// ================================================================================================================== //
+// The utilites here are for staying ABI compatible with the legacy `__compressed_pair`. They should not be used //
+// for new data structures. Use `_LIBCPP_NO_UNIQUE_ADDRESS` for new data structures instead (but make sure you //
+// understand how it works). //
+// ================================================================================================================== //
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename _Base2::reference second() _NOEXCEPT {
- return static_cast<_Base2&>(*this).__get();
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename _Base2::const_reference second() const _NOEXCEPT {
- return static_cast<_Base2 const&>(*this).__get();
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT {
- return static_cast<_Base1*>(__pair);
- }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT {
- return static_cast<_Base2*>(__pair);
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void swap(__compressed_pair& __x)
- _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
- using std::swap;
- swap(first(), __x.first());
- swap(second(), __x.second());
- }
+// The first member is aligned to the alignment of the second member to force padding in front of the compressed pair
+// in case there are members before it.
+//
+// For example:
+// (assuming x86-64 linux)
+// class SomeClass {
+// uint32_t member1;
+// _LIBCPP_COMPRESSED_PAIR(uint32_t, member2, uint64_t, member3);
+// }
+//
+// The layout with __compressed_pair is:
+// member1 - offset: 0, size: 4
+// padding - offset: 4, size: 4
+// member2 - offset: 8, size: 4
+// padding - offset: 12, size: 4
+// member3 - offset: 16, size: 8
+//
+// If the [[gnu::aligned]] wasn't there, the layout would instead be:
+// member1 - offset: 0, size: 4
+// member2 - offset: 4, size: 4
+// member3 - offset: 8, size: 8
+
+template <class _ToPad>
+class __compressed_pair_padding {
+ char __padding_[(is_empty<_ToPad>::value && !__libcpp_is_final<_ToPad>::value)
+ ? 0
+ : sizeof(_ToPad) - __datasizeof_v<_ToPad>];
};
-template <class _T1, class _T2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)
- _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
- __x.swap(__y);
-}
+# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
+ [[__gnu__::__aligned__(_LIBCPP_ALIGNOF(T2))]] _LIBCPP_NO_UNIQUE_ADDRESS T1 Initializer1; \
+ _LIBCPP_NO_UNIQUE_ADDRESS __compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
+ _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
+ _LIBCPP_NO_UNIQUE_ADDRESS __compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _)
+
+# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
+ [[using __gnu__: __aligned__(_LIBCPP_ALIGNOF(T2)), __aligned__(_LIBCPP_ALIGNOF(T3))]] \
+ _LIBCPP_NO_UNIQUE_ADDRESS T1 Initializer1; \
+ _LIBCPP_NO_UNIQUE_ADDRESS __compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
+ _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
+ _LIBCPP_NO_UNIQUE_ADDRESS __compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
+ _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
+ _LIBCPP_NO_UNIQUE_ADDRESS __compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _)
+
+#else
+# define _LIBCPP_COMPRESSED_PAIR(T1, Name1, T2, Name2) \
+ _LIBCPP_NO_UNIQUE_ADDRESS T1 Name1; \
+ _LIBCPP_NO_UNIQUE_ADDRESS T2 Name2
+
+# define _LIBCPP_COMPRESSED_TRIPLE(T1, Name1, T2, Name2, T3, Name3) \
+ _LIBCPP_NO_UNIQUE_ADDRESS T1 Name1; \
+ _LIBCPP_NO_UNIQUE_ADDRESS T2 Name2; \
+ _LIBCPP_NO_UNIQUE_ADDRESS T3 Name3
+#endif // _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
_LIBCPP_END_NAMESPACE_STD
-_LIBCPP_POP_MACROS
-
#endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 358a851958db1..c5362ce42b752 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -198,11 +198,11 @@ class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count {
template <class _Tp, class _Dp, class _Alloc>
class __shared_ptr_pointer : public __shared_weak_count {
- __compressed_pair<__compressed_pair<_Tp, _Dp>, _Alloc> __data_;
+ _LIBCPP_COMPRESSED_TRIPLE(_Tp, __ptr_, _Dp, __deleter_, _Alloc, __alloc_);
public:
_LIBCPP_HIDE_FROM_ABI __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a)
- : __data_(__compressed_pair<_Tp, _Dp>(__p, std::move(__d)), std::move(__a)) {}
+ : __ptr_(__p), __deleter_(std::move(__d)), __alloc_(std::move(__a)) {}
#ifndef _LIBCPP_HAS_NO_RTTI
_LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* __get_deleter(const type_info&) const _NOEXCEPT override;
@@ -217,15 +217,15 @@ class __shared_ptr_pointer : public __shared_weak_count {
template <class _Tp, class _Dp, class _Alloc>
const void* __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) const _NOEXCEPT {
- return __t == typeid(_Dp) ? std::addressof(__data_.first().second()) : nullptr;
+ return __t == typeid(_Dp) ? std::addressof(__deleter_) : nullptr;
}
#endif // _LIBCPP_HAS_NO_RTTI
template <class _Tp, class _Dp, class _Alloc>
void __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared() _NOEXCEPT {
- __data_.first().second()(__data_.first().first());
- __data_.first().second().~_Dp();
+ __deleter_(__ptr_);
+ __deleter_.~_Dp();
}
template <class _Tp, class _Dp, class _Alloc>
@@ -234,8 +234,8 @@ void __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT {
typedef allocator_traits<_Al> _ATraits;
typedef pointer_traits<typename _ATraits::pointer> _PTraits;
- _Al __a(__data_.second());
- __data_.second().~_Alloc();
+ _Al __a(__alloc_);
+ __alloc_.~_Alloc();
__a.deallocate(_PTraits::pointer_to(*this), 1);
}
@@ -293,36 +293,28 @@ struct __shared_ptr_emplace : __shared_weak_count {
allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1);
}
+ // TODO: It should be possible to refactor this to remove `_Storage` entirely.
// This class implements the control block for non-array shared pointers created
// through `std::allocate_shared` and `std::make_shared`.
- //
- // In previous versions of the library, we used a compressed pair to store
- // both the _Alloc and the _Tp. This implies using EBO, which is incompatible
- // with Allocator construction for _Tp. To allow implementing P0674 in C++20,
- // we now use a properly aligned char buffer while making sure that we maintain
- // the same layout that we had when we used a compressed pair.
- using _CompressedPair = __compressed_pair<_Alloc, _Tp>;
- struct _ALIGNAS_TYPE(_CompressedPair) _Storage {
- char __blob_[sizeof(_CompressedPair)];
+ struct _Storage {
+ struct _Data {
+ _LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, _Tp, __elem_);
+ };
+
+ _ALIGNAS_TYPE(_Data) char __buffer_[sizeof(_Data)];
_LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { ::new ((void*)__get_alloc()) _Alloc(std::move(__a)); }
_LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); }
+
_LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT {
- _CompressedPair* __as_pair = reinterpret_cast<_CompressedPair*>(__blob_);
- typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair);
- _Alloc* __alloc = reinterpret_cast<_Alloc*>(__first);
- return __alloc;
+ return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__alloc_);
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT {
- _CompressedPair* __as_pair = reinterpret_cast<_CompressedPair*>(__blob_);
- typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair);
- _Tp* __elem = reinterpret_cast<_Tp*>(__second);
- return __elem;
+ return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__elem_);
}
};
- static_assert(_LIBCPP_ALIGNOF(_Storage) == _LIBCPP_ALIGNOF(_CompressedPair), "");
- static_assert(sizeof(_Storage) == sizeof(_CompressedPair), "");
_Storage __storage_;
};
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 9519e4283868b..76cdcd83c2c5d 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -142,7 +142,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
void>;
private:
- __compressed_pair<pointer, deleter_type> __ptr_;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
typedef _LIBCPP_NODEBUG __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
@@ -176,23 +176,25 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
public:
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
- : __ptr_(__value_init_tag(), __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
- _LIBCPP_HIDE_FROM_ABI
- _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT
+ : __ptr_(__p),
+ __deleter_() {}
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(__p, __d) {}
+ : __ptr_(__p),
+ __deleter_(__d) {}
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(__p, std::move(__d)) {
+ : __ptr_(__p),
+ __deleter_(std::move(__d)) {
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
}
@@ -200,24 +202,26 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
_LIBCPP_HIDE_FROM_ABI unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
- : __ptr_(__u.release(), std::forward<deleter_type>(__u.get_deleter())) {}
+ : __ptr_(__u.release()),
+ __deleter_(std::forward<deleter_type>(__u.get_deleter())) {}
template <class _Up,
class _Ep,
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
class = _EnableIfDeleterConvertible<_Ep> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
- : __ptr_(__u.release(), std::forward<_Ep>(__u.get_deleter())) {}
+ : __ptr_(__u.release()),
+ __deleter_(std::forward<_Ep>(__u.get_deleter())) {}
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template <class _Up,
__enable_if_t<is_convertible<_Up*, _Tp*>::value && is_same<_Dp, default_delete<_Tp> >::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI unique_ptr(auto_ptr<_Up>&& __p) _NOEXCEPT : __ptr_(__p.release(), __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI unique_ptr(auto_ptr<_Up>&& __p) _NOEXCEPT : __ptr_(__p.release()), __deleter_() {}
#endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
reset(__u.release());
- __ptr_.second() = std::forward<deleter_type>(__u.get_deleter());
+ __deleter_ = std::forward<deleter_type>(__u.get_deleter());
return *this;
}
@@ -227,7 +231,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
class = _EnableIfDeleterAssignable<_Ep> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
reset(__u.release());
- __ptr_.second() = std::forward<_Ep>(__u.get_deleter());
+ __deleter_ = std::forward<_Ep>(__u.get_deleter());
return *this;
}
@@ -253,32 +257,36 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const {
- return *__ptr_.first();
+ return *__ptr_;
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_.first(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_.first(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __ptr_.second(); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT {
- return __ptr_.second();
+ return __deleter_;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT {
- return __ptr_.first() != nullptr;
+ return __ptr_ != nullptr;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT {
- pointer __t = __ptr_.first();
- __ptr_.first() = pointer();
+ pointer __t = __ptr_;
+ __ptr_ = pointer();
return __t;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(pointer __p = pointer()) _NOEXCEPT {
- pointer __tmp = __ptr_.first();
- __ptr_.first() = __p;
+ pointer __tmp = __ptr_;
+ __ptr_ = __p;
if (__tmp)
- __ptr_.second()(__tmp);
+ __deleter_(__tmp);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT { __ptr_.swap(__u.__ptr_); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT {
+ using std::swap;
+ swap(__ptr_, __u.__ptr_);
+ swap(__deleter_, __u.__deleter_);
+ }
};
template <class _Tp, class _Dp>
@@ -300,7 +308,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
void>;
private:
- __compressed_pair<pointer, deleter_type> __ptr_;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
template <class _From>
struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
@@ -349,42 +357,46 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
public:
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
- : __ptr_(__value_init_tag(), __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
template <class _Pp,
bool _Dummy = true,
class = _EnableIfDeleterDefaultConstructible<_Dummy>,
class = _EnableIfPointerConvertible<_Pp> >
- _LIBCPP_HIDE_FROM_ABI
- _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __p) _NOEXCEPT
+ : __ptr_(__p),
+ __deleter_() {}
template <class _Pp,
bool _Dummy = true,
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
class = _EnableIfPointerConvertible<_Pp> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(__p, __d) {}
+ : __ptr_(__p),
+ __deleter_(__d) {}
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(nullptr, __d) {}
+ : __ptr_(nullptr),
+ __deleter_(__d) {}
template <class _Pp,
bool _Dummy = true,
class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >,
class = _EnableIfPointerConvertible<_Pp> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(__p, std::move(__d)) {
+ : __ptr_(__p),
+ __deleter_(std::move(__d)) {
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
}
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
- : __ptr_(nullptr, std::move(__d)) {
+ : __ptr_(nullptr),
+ __deleter_(std::move(__d)) {
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
}
@@ -395,11 +407,12 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
_LIBCPP_HIDE_FROM_ABI unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
- : __ptr_(__u.release(), std::forward<deleter_type>(__u.get_deleter())) {}
+ : __ptr_(__u.release()),
+ __deleter_(std::forward<deleter_type>(__u.get_deleter())) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
reset(__u.release());
- __ptr_.second() = std::forward<deleter_type>(__u.get_deleter());
+ __deleter_ = std::forward<deleter_type>(__u.get_deleter());
return *this;
}
@@ -408,7 +421,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
class = _EnableIfDeleterConvertible<_Ep> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
- : __ptr_(__u.release(), std::forward<_Ep>(__u.get_deleter())) {}
+ : __ptr_(__u.release()),
+ __deleter_(std::forward<_Ep>(__u.get_deleter())) {}
template <class _Up,
class _Ep,
@@ -416,7 +430,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
class = _EnableIfDeleterAssignable<_Ep> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
reset(__u.release());
- __ptr_.second() = std::forward<_Ep>(__u.get_deleter());
+ __deleter_ = std::forward<_Ep>(__u.get_deleter());
return *this;
}
@@ -434,41 +448,45 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator[](size_t __i) const {
- return __ptr_.first()[__i];
+ return __ptr_[__i];
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_.first(); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __ptr_.second(); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT {
- return __ptr_.second();
+ return __deleter_;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT {
- return __ptr_.first() != nullptr;
+ return __ptr_ != nullptr;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT {
- pointer __t = __ptr_.first();
- __ptr_.first() = pointer();
+ pointer __t = __ptr_;
+ __ptr_ = pointer();
return __t;
}
template <class _Pp, __enable_if_t<_CheckArrayPointerConversion<_Pp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(_Pp __p) _NOEXCEPT {
- pointer __tmp = __ptr_.first();
- __ptr_.first() = __p;
+ pointer __tmp = __ptr_;
+ __ptr_ = __p;
if (__tmp)
- __ptr_.second()(__tmp);
+ __deleter_(__tmp);
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(nullptr_t = nullptr) _NOEXCEPT {
- pointer __tmp = __ptr_.first();
- __ptr_.first() = nullptr;
+ pointer __tmp = __ptr_;
+ __ptr_ = nullptr;
if (__tmp)
- __ptr_.second()(__tmp);
+ __deleter_(__tmp);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT { __ptr_.swap(__u.__ptr_); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT {
+ using std::swap;
+ swap(__ptr_, __u.__ptr_);
+ swap(__deleter_, __u.__deleter_);
+ }
};
template <class _Tp, class _Dp, __enable_if_t<__is_swappable_v<_Dp>, int> = 0>
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index bab724d1b8963..7916769bd83bf 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -78,7 +78,7 @@ public:
pointer __first_;
pointer __begin_;
pointer __end_;
- __compressed_pair<pointer, allocator_type> __end_cap_;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __end_cap_, allocator_type, __alloc_);
using __alloc_ref = __add_lvalue_reference_t<allocator_type>;
using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>;
@@ -88,13 +88,13 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) {}
+ : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {}
+ : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
- : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {}
+ : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
@@ -111,15 +111,11 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __end_cap_.second(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT {
- return __end_cap_.second();
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __alloc_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT { return __alloc_; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_.first(); }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {
- return __end_cap_.first();
- }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT { return __end_cap_; }
_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_; }
@@ -346,7 +342,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
- : __end_cap_(nullptr, __a) {
+ : __end_cap_(nullptr), __alloc_(__a) {
if (__cap == 0) {
__first_ = nullptr;
} else {
@@ -371,7 +367,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__
: __first_(std::move(__c.__first_)),
__begin_(std::move(__c.__begin_)),
__end_(std::move(__c.__end_)),
- __end_cap_(std::move(__c.__end_cap_)) {
+ __end_cap_(std::move(__c.__end_cap_)),
+ __alloc_(std::move(__c.__alloc_)) {
__c.__first_ = nullptr;
__c.__begin_ = nullptr;
__c.__end_ = nullptr;
@@ -381,7 +378,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
- : __end_cap_(nullptr, __a) {
+ : __end_cap_(nullptr), __alloc_(__a) {
if (__a == __c.__alloc()) {
__first_ = __c.__first_;
__begin_ = __c.__begin_;
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 1990fa602d39c..6ded2c597f6fa 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -932,21 +932,21 @@ private:
private:
__iter_pointer __begin_node_;
- __compressed_pair<__end_node_t, __node_allocator> __pair1_;
- __compressed_pair<size_type, value_compare> __pair3_;
+ _LIBCPP_COMPRESSED_PAIR(__end_node_t, __end_node_, __node_allocator, __node_alloc_);
+ _LIBCPP_COMPRESSED_PAIR(size_type, __size_, value_compare, __value_comp_);
public:
_LIBCPP_HIDE_FROM_ABI __iter_pointer __end_node() _NOEXCEPT {
- return static_cast<__iter_pointer>(pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()));
+ return static_cast<__iter_pointer>(pointer_traits<__end_node_ptr>::pointer_to(__end_node_));
}
_LIBCPP_HIDE_FROM_ABI __iter_pointer __end_node() const _NOEXCEPT {
return static_cast<__iter_pointer>(
- pointer_traits<__end_node_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first())));
+ pointer_traits<__end_node_ptr>::pointer_to(const_cast<__end_node_t&>(__end_node_)));
}
- _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __pair1_.second(); }
+ _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; }
private:
- _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __pair1_.second(); }
+ _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; }
_LIBCPP_HIDE_FROM_ABI __iter_pointer& __begin_node() _NOEXCEPT { return __begin_node_; }
_LIBCPP_HIDE_FROM_ABI const __iter_pointer& __begin_node() const _NOEXCEPT { return __begin_node_; }
@@ -954,12 +954,12 @@ public:
_LIBCPP_HIDE_FROM_ABI allocator_type __alloc() const _NOEXCEPT { return allocator_type(__node_alloc()); }
private:
- _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __pair3_.first(); }
+ _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __size_; }
public:
- _LIBCPP_HIDE_FROM_ABI const size_type& size() const _NOEXCEPT { return __pair3_.first(); }
- _LIBCPP_HIDE_FROM_ABI value_compare& value_comp() _NOEXCEPT { return __pair3_.second(); }
- _LIBCPP_HIDE_FROM_ABI const value_compare& value_comp() const _NOEXCEPT { return __pair3_.second(); }
+ _LIBCPP_HIDE_FROM_ABI const size_type& size() const _NOEXCEPT { return __size_; }
+ _LIBCPP_HIDE_FROM_ABI value_compare& value_comp() _NOEXCEPT { return __value_comp_; }
+ _LIBCPP_HIDE_FROM_ABI const value_compare& value_comp() const _NOEXCEPT { return __value_comp_; }
public:
_LIBCPP_HIDE_FROM_ABI __node_pointer __root() const _NOEXCEPT {
@@ -1324,21 +1324,19 @@ private:
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) _NOEXCEPT_(
is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_copy_constructible<value_compare>::value)
- : __pair3_(0, __comp) {
+ : __size_(0), __value_comp_(__comp) {
__begin_node() = __end_node();
}
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
- : __begin_node_(__iter_pointer()),
- __pair1_(__default_init_tag(), __node_allocator(__a)),
- __pair3_(0, __default_init_tag()) {
+ : __begin_node_(__iter_pointer()), __node_alloc_(__node_allocator(__a)), __size_(0) {
__begin_node() = __end_node();
}
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, const allocator_type& __a)
- : __begin_node_(__iter_pointer()), __pair1_(__default_init_tag(), __node_allocator(__a)), __pair3_(0, __comp) {
+ : __begin_node_(__iter_pointer()), __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(__comp) {
__begin_node() = __end_node();
}
@@ -1437,8 +1435,9 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
: __begin_node_(__iter_pointer()),
- __pair1_(__default_init_tag(), __node_traits::select_on_container_copy_construction(__t.__node_alloc())),
- __pair3_(0, __t.value_comp()) {
+ __node_alloc_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
+ __size_(0),
+ __value_comp_(__t.value_comp()) {
__begin_node() = __end_node();
}
@@ -1446,8 +1445,10 @@ template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_(
is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<value_compare>::value)
: __begin_node_(std::move(__t.__begin_node_)),
- __pair1_(std::move(__t.__pair1_)),
- __pair3_(std::move(__t.__pair3_)) {
+ __end_node_(std::move(__t.__end_node_)),
+ __node_alloc_(std::move(__t.__node_alloc_)),
+ __size_(__t.__size_),
+ __value_comp_(std::move(__t.__value_comp_)) {
if (size() == 0)
__begin_node() = __end_node();
else {
@@ -1460,7 +1461,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_(
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
- : __pair1_(__default_init_tag(), __node_allocator(__a)), __pair3_(0, std::move(__t.value_comp())) {
+ : __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(std::move(__t.value_comp())) {
if (__a == __t.__alloc()) {
if (__t.size() == 0)
__begin_node() = __end_node();
@@ -1482,10 +1483,11 @@ template <class _Tp, class _Compare, class _Allocator>
void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value&& is_nothrow_move_assignable<__node_allocator>::value) {
destroy(static_cast<__node_pointer>(__end_node()->__left_));
- __begin_node_ = __t.__begin_node_;
- __pair1_.first() = __t.__pair1_.first();
+ __begin_node_ = __t.__begin_node_;
+ __end_node_ = __t.__end_node_;
__move_assign_alloc(__t);
- __pair3_ = std::move(__t.__pair3_);
+ __size_ = __t.__size_;
+ __value_comp_ = std::move(__t.__value_comp_);
if (size() == 0)
__begin_node() = __end_node();
else {
@@ -1554,9 +1556,10 @@ void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
{
using std::swap;
swap(__begin_node_, __t.__begin_node_);
- swap(__pair1_.first(), __t.__pair1_.first());
+ swap(__end_node_, __t.__end_node_);
std::__swap_allocator(__node_alloc(), __t.__node_alloc());
- __pair3_.swap(__t.__pair3_);
+ swap(__size_, __t.__size_);
+ swap(__value_comp_, __t.__value_comp_);
if (size() == 0)
__begin_node() = __end_node();
else
diff --git a/libcxx/include/__type_traits/datasizeof.h b/libcxx/include/__type_traits/datasizeof.h
index 35c12921e8ffa..1b324e470d0b0 100644
--- a/libcxx/include/__type_traits/datasizeof.h
+++ b/libcxx/include/__type_traits/datasizeof.h
@@ -54,9 +54,13 @@ struct _FirstPaddingByte<_Tp, true> {
// the use as an extension.
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
+_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
template <class _Tp>
inline const size_t __datasizeof_v = offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_);
_LIBCPP_DIAGNOSTIC_POP
+
+template <class _Tp>
+inline const size_t __datasizeof_v<_Tp&> = __datasizeof_v<_Tp>;
#endif // __has_extension(datasizeof)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 43ed8c46866ec..e184323212c32 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -561,12 +561,12 @@ private:
__map __map_;
size_type __start_;
- __compressed_pair<size_type, allocator_type> __size_;
+ _LIBCPP_COMPRESSED_PAIR(size_type, __size_, allocator_type, __alloc_);
public:
// construct/copy/destroy:
_LIBCPP_HIDE_FROM_ABI deque() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __start_(0), __size_(0, __default_init_tag()) {
+ : __start_(0), __size_(0) {
__annotate_new(0);
}
@@ -580,7 +580,7 @@ public:
}
_LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
}
@@ -592,7 +592,7 @@ public:
template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI deque(size_type __n, const value_type& __v, const allocator_type& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
if (__n > 0)
__append(__n, __v);
@@ -606,7 +606,7 @@ public:
#if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI deque(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
__append_with_size(ranges::begin(__range), ranges::distance(__range));
@@ -669,8 +669,8 @@ public:
_LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v);
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __size_.second(); }
- _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __size_.second(); }
+ _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __alloc_; }
+ _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __alloc_; }
// iterators:
@@ -709,8 +709,8 @@ public:
// capacity:
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size(); }
- _LIBCPP_HIDE_FROM_ABI size_type& __size() _NOEXCEPT { return __size_.first(); }
- _LIBCPP_HIDE_FROM_ABI const size_type& __size() const _NOEXCEPT { return __size_.first(); }
+ _LIBCPP_HIDE_FROM_ABI size_type& __size() _NOEXCEPT { return __size_; }
+ _LIBCPP_HIDE_FROM_ABI const size_type& __size() const _NOEXCEPT { return __size_; }
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
return std::min<size_type>(__alloc_traits::max_size(__alloc()), numeric_limits<difference_type>::max());
@@ -1230,7 +1230,7 @@ deque(from_range_t, _Range&&, _Alloc = _Alloc()) -> deque<ranges::range_value_t<
#endif
template <class _Tp, class _Allocator>
-deque<_Tp, _Allocator>::deque(size_type __n) : __start_(0), __size_(0, __default_init_tag()) {
+deque<_Tp, _Allocator>::deque(size_type __n) : __start_(0), __size_(0) {
__annotate_new(0);
if (__n > 0)
__append(__n);
@@ -1239,7 +1239,7 @@ deque<_Tp, _Allocator>::deque(size_type __n) : __start_(0), __size_(0, __default
#if _LIBCPP_STD_VER >= 14
template <class _Tp, class _Allocator>
deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
if (__n > 0)
__append(__n);
@@ -1247,7 +1247,7 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a)
#endif
template <class _Tp, class _Allocator>
-deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) : __start_(0), __size_(0, __default_init_tag()) {
+deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) : __start_(0), __size_(0) {
__annotate_new(0);
if (__n > 0)
__append(__n, __v);
@@ -1255,7 +1255,7 @@ deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) : __start_(0
template <class _Tp, class _Allocator>
template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> >
-deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l) : __start_(0), __size_(0, __default_init_tag()) {
+deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l) : __start_(0), __size_(0) {
__annotate_new(0);
__append(__f, __l);
}
@@ -1263,7 +1263,7 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l) : __start_(0), __s
template <class _Tp, class _Allocator>
template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> >
deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, const allocator_type& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
__append(__f, __l);
}
@@ -1272,14 +1272,15 @@ template <class _Tp, class _Allocator>
deque<_Tp, _Allocator>::deque(const deque& __c)
: __map_(__pointer_allocator(__alloc_traits::select_on_container_copy_construction(__c.__alloc()))),
__start_(0),
- __size_(0, __map_.__alloc()) {
+ __size_(0),
+ __alloc_(__map_.__alloc()) {
__annotate_new(0);
__append(__c.begin(), __c.end());
}
template <class _Tp, class _Allocator>
deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t<allocator_type>& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
__append(__c.begin(), __c.end());
}
@@ -1296,21 +1297,24 @@ deque<_Tp, _Allocator>& deque<_Tp, _Allocator>::operator=(const deque& __c) {
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Allocator>
-deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il) : __start_(0), __size_(0, __default_init_tag()) {
+deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il) : __start_(0), __size_(0) {
__annotate_new(0);
__append(__il.begin(), __il.end());
}
template <class _Tp, class _Allocator>
deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il, const allocator_type& __a)
- : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+ : __map_(__pointer_allocator(__a)), __start_(0), __size_(0), __alloc_(__a) {
__annotate_new(0);
__append(__il.begin(), __il.end());
}
template <class _Tp, class _Allocator>
inline deque<_Tp, _Allocator>::deque(deque&& __c) noexcept(is_nothrow_move_constructible<allocator_type>::value)
- : __map_(std::move(__c.__map_)), __start_(std::move(__c.__start_)), __size_(std::move(__c.__size_)) {
+ : __map_(std::move(__c.__map_)),
+ __start_(std::move(__c.__start_)),
+ __size_(std::move(__c.__size_)),
+ __alloc_(std::move(__c.__alloc_)) {
__c.__start_ = 0;
__c.__size() = 0;
}
@@ -1319,7 +1323,8 @@ template <class _Tp, class _Allocator>
inline deque<_Tp, _Allocator>::deque(deque&& __c, const __type_identity_t<allocator_type>& __a)
: __map_(std::move(__c.__map_), __pointer_allocator(__a)),
__start_(std::move(__c.__start_)),
- __size_(std::move(__c.__size()), __a) {
+ __size_(std::move(__c.__size_)),
+ __alloc_(__a) {
if (__a == __c.__alloc()) {
__c.__start_ = 0;
__c.__size() = 0;
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index e59c210654caa..8e457141b819f 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -227,6 +227,7 @@ template <class T, class Allocator, class Predicate>
#include <__type_traits/type_identity.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/swap.h>
#include <limits>
#include <new> // __launder
#include <version>
@@ -489,27 +490,27 @@ protected:
typedef __rebind_alloc<allocator_traits<allocator_type>, __begin_node> __begin_node_allocator;
typedef typename allocator_traits<__begin_node_allocator>::pointer __begin_node_pointer;
- __compressed_pair<__begin_node, __node_allocator> __before_begin_;
+ _LIBCPP_COMPRESSED_PAIR(__begin_node, __before_begin_, __node_allocator, __alloc_);
_LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() _NOEXCEPT {
- return pointer_traits<__begin_node_pointer>::pointer_to(__before_begin_.first());
+ return pointer_traits<__begin_node_pointer>::pointer_to(__before_begin_);
}
_LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() const _NOEXCEPT {
- return pointer_traits<__begin_node_pointer>::pointer_to(const_cast<__begin_node&>(__before_begin_.first()));
+ return pointer_traits<__begin_node_pointer>::pointer_to(const_cast<__begin_node&>(__before_begin_));
}
- _LIBCPP_HIDE_FROM_ABI __node_allocator& __alloc() _NOEXCEPT { return __before_begin_.second(); }
- _LIBCPP_HIDE_FROM_ABI const __node_allocator& __alloc() const _NOEXCEPT { return __before_begin_.second(); }
+ _LIBCPP_HIDE_FROM_ABI __node_allocator& __alloc() _NOEXCEPT { return __alloc_; }
+ _LIBCPP_HIDE_FROM_ABI const __node_allocator& __alloc() const _NOEXCEPT { return __alloc_; }
typedef __forward_list_iterator<__node_pointer> iterator;
typedef __forward_list_const_iterator<__node_pointer> const_iterator;
_LIBCPP_HIDE_FROM_ABI __forward_list_base() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
- : __before_begin_(__begin_node(), __default_init_tag()) {}
+ : __before_begin_(__begin_node()) {}
_LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const allocator_type& __a)
- : __before_begin_(__begin_node(), __node_allocator(__a)) {}
+ : __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) {}
_LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const __node_allocator& __a)
- : __before_begin_(__begin_node(), __a) {}
+ : __before_begin_(__begin_node()), __alloc_(__a) {}
public:
#ifndef _LIBCPP_CXX03_LANG
@@ -591,13 +592,13 @@ private:
template <class _Tp, class _Alloc>
inline __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x) noexcept(
is_nothrow_move_constructible<__node_allocator>::value)
- : __before_begin_(std::move(__x.__before_begin_)) {
+ : __before_begin_(std::move(__x.__before_begin_)), __alloc_(std::move(__x.__alloc_)) {
__x.__before_begin()->__next_ = nullptr;
}
template <class _Tp, class _Alloc>
inline __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x, const allocator_type& __a)
- : __before_begin_(__begin_node(), __node_allocator(__a)) {
+ : __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) {
if (__alloc() == __x.__alloc()) {
__before_begin()->__next_ = __x.__before_begin()->__next_;
__x.__before_begin()->__next_ = nullptr;
diff --git a/libcxx/include/future b/libcxx/include/future
index dea73dc6389bc..841ee29049f27 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -1401,13 +1401,13 @@ class __packaged_task_func;
template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
class __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __packaged_task_base<_Rp(_ArgTypes...)> {
- __compressed_pair<_Fp, _Alloc> __f_;
+ _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Alloc, __alloc_);
public:
- _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(const _Fp& __f) : __f_(__f, __default_init_tag()) {}
- _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(_Fp&& __f) : __f_(std::move(__f), __default_init_tag()) {}
- _LIBCPP_HIDE_FROM_ABI __packaged_task_func(const _Fp& __f, const _Alloc& __a) : __f_(__f, __a) {}
- _LIBCPP_HIDE_FROM_ABI __packaged_task_func(_Fp&& __f, const _Alloc& __a) : __f_(std::move(__f), __a) {}
+ _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(const _Fp& __f) : __func_(__f) {}
+ _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(_Fp&& __f) : __func_(std::move(__f)) {}
+ _LIBCPP_HIDE_FROM_ABI __packaged_task_func(const _Fp& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {}
+ _LIBCPP_HIDE_FROM_ABI __packaged_task_func(_Fp&& __f, const _Alloc& __a) : __func_(std::move(__f)), __alloc_(__a) {}
_LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy();
_LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate();
@@ -1417,12 +1417,13 @@ public:
template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to(
__packaged_task_base<_Rp(_ArgTypes...)>* __p) _NOEXCEPT {
- ::new ((void*)__p) __packaged_task_func(std::move(__f_.first()), std::move(__f_.second()));
+ ::new ((void*)__p) __packaged_task_func(std::move(__func_), std::move(__alloc_));
}
template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() {
- __f_.~__compressed_pair<_Fp, _Alloc>();
+ __func_.~_Fp();
+ __alloc_.~_Alloc();
}
template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
@@ -1430,14 +1431,15 @@ void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate()
typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap;
typedef allocator_traits<_Ap> _ATraits;
typedef pointer_traits<typename _ATraits::pointer> _PTraits;
- _Ap __a(__f_.second());
- __f_.~__compressed_pair<_Fp, _Alloc>();
+ _Ap __a(__alloc_);
+ __func_.~_Fp();
+ __alloc_.~_Alloc();
__a.deallocate(_PTraits::pointer_to(*this), 1);
}
template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
_Rp __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&&... __arg) {
- return std::__invoke(__f_.first(), std::forward<_ArgTypes>(__arg)...);
+ return std::__invoke(__func_, std::forward<_ArgTypes>(__arg)...);
}
template <class _Callable>
diff --git a/libcxx/include/list b/libcxx/include/list
index 57e5c05da9f06..d1fe8d354f407 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -497,16 +497,16 @@ protected:
"internal allocator type must differ from user-specified type; otherwise overload resolution breaks");
__node_base __end_;
- __compressed_pair<size_type, __node_allocator> __size_alloc_;
+ _LIBCPP_COMPRESSED_PAIR(size_type, __size_, __node_allocator, __node_alloc_);
_LIBCPP_HIDE_FROM_ABI __link_pointer __end_as_link() const _NOEXCEPT {
return __node_pointer_traits::__unsafe_link_pointer_cast(const_cast<__node_base&>(__end_).__self());
}
- _LIBCPP_HIDE_FROM_ABI size_type& __sz() _NOEXCEPT { return __size_alloc_.first(); }
- _LIBCPP_HIDE_FROM_ABI const size_type& __sz() const _NOEXCEPT { return __size_alloc_.first(); }
- _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __size_alloc_.second(); }
- _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __size_alloc_.second(); }
+ _LIBCPP_HIDE_FROM_ABI size_type& __sz() _NOEXCEPT { return __size_; }
+ _LIBCPP_HIDE_FROM_ABI const size_type& __sz() const _NOEXCEPT { return __size_; }
+ _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; }
+ _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; }
_LIBCPP_HIDE_FROM_ABI size_type __node_alloc_max_size() const _NOEXCEPT {
return __node_alloc_traits::max_size(__node_alloc());
@@ -600,17 +600,20 @@ inline void __list_imp<_Tp, _Alloc>::__unlink_nodes(__link_pointer __f, __link_p
template <class _Tp, class _Alloc>
inline __list_imp<_Tp, _Alloc>::__list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
- : __size_alloc_(0, __default_init_tag()) {}
+ : __size_(0) {}
template <class _Tp, class _Alloc>
-inline __list_imp<_Tp, _Alloc>::__list_imp(const allocator_type& __a) : __size_alloc_(0, __node_allocator(__a)) {}
+inline __list_imp<_Tp, _Alloc>::__list_imp(const allocator_type& __a)
+ : __size_(0), __node_alloc_(__node_allocator(__a)) {}
template <class _Tp, class _Alloc>
-inline __list_imp<_Tp, _Alloc>::__list_imp(const __node_allocator& __a) : __size_alloc_(0, __a) {}
+inline __list_imp<_Tp, _Alloc>::__list_imp(const __node_allocator& __a) : __size_(0), __node_alloc_(__a) {}
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Alloc>
-inline __list_imp<_Tp, _Alloc>::__list_imp(__node_allocator&& __a) _NOEXCEPT : __size_alloc_(0, std::move(__a)) {}
+inline __list_imp<_Tp, _Alloc>::__list_imp(__node_allocator&& __a) _NOEXCEPT
+ : __size_(0),
+ __node_alloc_(std::move(__a)) {}
#endif
template <class _Tp, class _Alloc>
diff --git a/libcxx/include/string b/libcxx/include/string
index 54d24c88a9c3f..1cecb0c2776b9 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -872,18 +872,18 @@ private:
__long __l;
};
- __compressed_pair<__rep, allocator_type> __r_;
+ _LIBCPP_COMPRESSED_PAIR(__rep, __rep_, allocator_type, __alloc_);
// Construct a string with the given allocator and enough storage to hold `__size` characters, but
// don't initialize the characters. The contents of the string, including the null terminator, must be
// initialized separately.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(
__uninitialized_size_tag, size_type __size, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
if (__size > max_size())
__throw_length_error();
if (__fits_in_sso(__size)) {
- __r_.first() = __rep();
+ __rep_ = __rep();
__set_short_size(__size);
} else {
auto __capacity = __recommend(__size) + 1;
@@ -899,7 +899,7 @@ private:
template <class _Iter, class _Sent>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__init_with_sentinel(std::move(__first), std::move(__last));
}
@@ -914,7 +914,7 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string()
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __r_(__value_init_tag(), __default_init_tag()) {
+ : __rep_() {
__annotate_new(0);
}
@@ -924,14 +924,14 @@ public:
#else
_NOEXCEPT
#endif
- : __r_(__value_init_tag(), __a) {
+ : __rep_(), __alloc_(__a) {
__annotate_new(0);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str)
- : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) {
+ : __alloc_(__alloc_traits::select_on_container_copy_construction(__str.__alloc())) {
if (!__str.__is_long()) {
- __r_.first() = __str.__r_.first();
+ __rep_ = __str.__rep_;
__annotate_new(__get_short_size());
} else
__init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
@@ -939,9 +939,9 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
basic_string(const basic_string& __str, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
if (!__str.__is_long()) {
- __r_.first() = __str.__r_.first();
+ __rep_ = __str.__rep_;
__annotate_new(__get_short_size());
} else
__init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
@@ -957,28 +957,29 @@ public:
// Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
// does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first.
// __str's memory needs to be unpoisoned only in the case where it's a short string.
- : __r_([](basic_string& __s) -> decltype(__s.__r_)&& {
+ : __rep_([](basic_string& __s) -> decltype(__s.__rep_)&& {
if (!__s.__is_long())
__s.__annotate_delete();
- return std::move(__s.__r_);
- }(__str)) {
- __str.__r_.first() = __rep();
+ return std::move(__s.__rep_);
+ }(__str)),
+ __alloc_(std::move(__str.__alloc_)) {
+ __str.__rep_ = __rep();
__str.__annotate_new(0);
if (!__is_long())
__annotate_new(size());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
__init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
else {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
if (!__str.__is_long())
__str.__annotate_delete();
- __r_.first() = __str.__r_.first();
- __str.__r_.first() = __rep();
+ __rep_ = __str.__rep_;
+ __str.__rep_ = __rep();
__str.__annotate_new(0);
if (!__is_long() && this != &__str)
__annotate_new(size());
@@ -987,15 +988,14 @@ public:
#endif // _LIBCPP_CXX03_LANG
template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s)
- : __r_(__default_init_tag(), __default_init_tag()) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) {
_LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*) detected nullptr");
__init(__s, traits_type::length(__s));
}
template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
_LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*, allocator) detected nullptr");
__init(__s, traits_type::length(__s));
}
@@ -1004,23 +1004,19 @@ public:
basic_string(nullptr_t) = delete;
#endif
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n)
- : __r_(__default_init_tag(), __default_init_tag()) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) {
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr");
__init(__s, __n);
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
_LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr");
__init(__s, __n);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c)
- : __r_(__default_init_tag(), __default_init_tag()) {
- __init(__n, __c);
- }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c) { __init(__n, __c); }
#if _LIBCPP_STD_VER >= 23
_LIBCPP_HIDE_FROM_ABI constexpr basic_string(
@@ -1029,7 +1025,7 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr basic_string(
basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator())
- : __r_(__default_init_tag(), __alloc) {
+ : __alloc_(__alloc) {
if (__pos > __str.size())
__throw_out_of_range();
@@ -1045,13 +1041,13 @@ public:
template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__init(__n, __c);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator())
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
size_type __str_sz = __str.size();
if (__pos > __str_sz)
__throw_out_of_range();
@@ -1060,7 +1056,7 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator())
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
size_type __str_sz = __str.size();
if (__pos > __str_sz)
__throw_out_of_range();
@@ -1073,7 +1069,7 @@ public:
int> = 0>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type())
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__self_view __sv0 = __t;
__self_view __sv = __sv0.substr(__pos, __n);
__init(__sv.data(), __sv.size());
@@ -1083,8 +1079,8 @@ public:
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
!__is_same_uncvref<_Tp, basic_string>::value,
int> = 0>
- _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t)
- : __r_(__default_init_tag(), __default_init_tag()) {
+ _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(
+ const _Tp& __t) {
__self_view __sv = __t;
__init(__sv.data(), __sv.size());
}
@@ -1095,21 +1091,20 @@ public:
int> = 0>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__self_view __sv = __t;
__init(__sv.data(), __sv.size());
}
template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last)
- : __r_(__default_init_tag(), __default_init_tag()) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last) {
__init(__first, __last);
}
template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__init(__first, __last);
}
@@ -1117,7 +1112,7 @@ public:
template <_ContainerCompatibleRange<_CharT> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string(
from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
__init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range));
} else {
@@ -1127,13 +1122,12 @@ public:
#endif
#ifndef _LIBCPP_CXX03_LANG
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il)
- : __r_(__default_init_tag(), __default_init_tag()) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) {
__init(__il.begin(), __il.end());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a)
- : __r_(__default_init_tag(), __a) {
+ : __alloc_(__a) {
__init(__il.begin(), __il.end());
}
#endif // _LIBCPP_CXX03_LANG
@@ -1398,8 +1392,8 @@ public:
size_type __old_sz = __str.size();
if (!__str.__is_long())
__str.__annotate_delete();
- __r_.first() = __str.__r_.first();
- __str.__r_.first() = __rep();
+ __rep_ = __str.__rep_;
+ __str.__rep_ = __rep();
__str.__annotate_new(0);
_Traits::move(data(), data() + __pos, __len);
@@ -1806,10 +1800,10 @@ private:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS bool
__is_long() const _NOEXCEPT {
- if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) {
- return __r_.first().__l.__is_long_;
+ if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__rep_.__l.__is_long_)) {
+ return __rep_.__l.__is_long_;
}
- return __r_.first().__s.__is_long_;
+ return __rep_.__s.__is_long_;
}
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) {
@@ -1862,27 +1856,27 @@ private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
__insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n);
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __alloc_; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __alloc_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void
__set_short_size(size_type __s) _NOEXCEPT {
_LIBCPP_ASSERT_INTERNAL(__s < __min_cap, "__s should never be greater than or equal to the short string capacity");
- __r_.first().__s.__size_ = __s;
- __r_.first().__s.__is_long_ = false;
+ __rep_.__s.__size_ = __s;
+ __rep_.__s.__is_long_ = false;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS size_type
__get_short_size() const _NOEXCEPT {
- _LIBCPP_ASSERT_INTERNAL(!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size");
- return __r_.first().__s.__size_;
+ _LIBCPP_ASSERT_INTERNAL(!__rep_.__s.__is_long_, "String has to be short when trying to get the short size");
+ return __rep_.__s.__size_;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_size(size_type __s) _NOEXCEPT {
- __r_.first().__l.__size_ = __s;
+ __rep_.__l.__size_ = __s;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_size() const _NOEXCEPT {
- return __r_.first().__l.__size_;
+ return __rep_.__l.__size_;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_size(size_type __s) _NOEXCEPT {
if (__is_long())
@@ -1892,31 +1886,36 @@ private:
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_cap(size_type __s) _NOEXCEPT {
- __r_.first().__l.__cap_ = __s / __endian_factor;
- __r_.first().__l.__is_long_ = true;
+ __rep_.__l.__cap_ = __s / __endian_factor;
+ __rep_.__l.__is_long_ = true;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_cap() const _NOEXCEPT {
- return __r_.first().__l.__cap_ * __endian_factor;
+ return __rep_.__l.__cap_ * __endian_factor;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_pointer(pointer __p) _NOEXCEPT {
- __r_.first().__l.__data_ = __p;
+ __rep_.__l.__data_ = __p;
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer() _NOEXCEPT {
- return _LIBCPP_ASAN_VOLATILE_WRAPPER(__r_.first().__l.__data_);
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER(__rep_.__l.__data_);
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer() const _NOEXCEPT {
- return _LIBCPP_ASAN_VOLATILE_WRAPPER(__r_.first().__l.__data_);
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER(__rep_.__l.__data_);
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS pointer
__get_short_pointer() _NOEXCEPT {
- return _LIBCPP_ASAN_VOLATILE_WRAPPER(pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]));
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER(pointer_traits<pointer>::pointer_to(__rep_.__s.__data_[0]));
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS const_pointer
__get_short_pointer() const _NOEXCEPT {
- return _LIBCPP_ASAN_VOLATILE_WRAPPER(pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]));
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER(pointer_traits<const_pointer>::pointer_to(__rep_.__s.__data_[0]));
}
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer() _NOEXCEPT {
return __is_long() ? __get_long_pointer() : __get_short_pointer();
}
@@ -2208,7 +2207,7 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
if (__reserve > max_size())
__throw_length_error();
pointer __p;
@@ -2232,7 +2231,7 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz) {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
if (__sz > max_size())
__throw_length_error();
pointer __p;
@@ -2256,7 +2255,7 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void
basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value_type* __s, size_type __sz) {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
pointer __p;
if (__fits_in_sso(__sz)) {
@@ -2279,7 +2278,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
if (__n > max_size())
__throw_length_error();
@@ -2311,7 +2310,7 @@ template <class _CharT, class _Traits, class _Allocator>
template <class _InputIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) {
- __r_.first() = __rep();
+ __rep_ = __rep();
__annotate_new(0);
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
@@ -2342,7 +2341,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz) {
if (__libcpp_is_constant_evaluated())
- __r_.first() = __rep();
+ __rep_ = __rep();
if (__sz > max_size())
__throw_length_error();
@@ -2563,7 +2562,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
size_type __old_size = __get_short_size();
if (__get_short_size() < __str.__get_short_size())
__annotate_increase(__str.__get_short_size() - __get_short_size());
- __r_.first() = __str.__r_.first();
+ __rep_ = __str.__rep_;
if (__old_size > __get_short_size())
__annotate_shrink(__old_size);
} else {
@@ -2611,7 +2610,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
bool __str_was_short = !__str.__is_long();
__move_assign_alloc(__str);
- __r_.first() = __str.__r_.first();
+ __rep_ = __str.__rep_;
__str.__set_short_size(0);
traits_type::assign(__str.__get_short_pointer()[0], value_type());
@@ -3347,7 +3346,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
__annotate_delete();
if (this != &__str && !__str.__is_long())
__str.__annotate_delete();
- std::swap(__r_.first(), __str.__r_.first());
+ std::swap(__rep_, __str.__rep_);
std::__swap_allocator(__alloc(), __str.__alloc());
if (!__is_long())
__annotate_new(__get_short_size());
@@ -3710,7 +3709,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
if (__is_long()) {
__annotate_delete();
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
- __r_.first() = __rep();
+ __rep_ = __rep();
}
}
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 014971b4a680e..f80282ebdef6d 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -430,7 +430,7 @@ public:
#else
_NOEXCEPT
#endif
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -444,7 +444,7 @@ public:
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -466,7 +466,7 @@ public:
template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
if (__n > 0) {
__vallocate(__n);
__construct_at_end(__n, __x);
@@ -504,7 +504,7 @@ public:
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __end_cap_(nullptr, __alloc) {
+ : __alloc_(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -760,8 +760,7 @@ public:
private:
pointer __begin_ = nullptr;
pointer __end_ = nullptr;
- __compressed_pair<pointer, allocator_type> __end_cap_ =
- __compressed_pair<pointer, allocator_type>(nullptr, __default_init_tag());
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
// Allocate space for __n objects
// throws length_error if __n > max_size()
@@ -930,17 +929,14 @@ private:
++__tx.__pos_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT {
- return this->__end_cap_.second();
- }
+ // TODO: Remove these now redundant accessors
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return this->__alloc_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT {
- return this->__end_cap_.second();
- }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT {
- return this->__end_cap_.first();
+ return this->__alloc_;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return this->__cap_; }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {
- return this->__end_cap_.first();
+ return this->__cap_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __clear() _NOEXCEPT {
@@ -1174,7 +1170,7 @@ template <class _InputIterator,
int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
__init_with_sentinel(__first, __last);
}
@@ -1195,21 +1191,21 @@ template <class _ForwardIterator,
int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x)
- : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) {
+ : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) {
__init_with_size(__x.__begin_, __x.__end_, __x.size());
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
__init_with_size(__x.__begin_, __x.__end_, __x.size());
}
@@ -1220,7 +1216,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __end_cap_(nullptr, std::move(__x.__alloc())) {
+ : __alloc_(std::move(__x.__alloc())) {
this->__begin_ = __x.__begin_;
this->__end_ = __x.__end_;
this->__end_cap() = __x.__end_cap();
@@ -1230,7 +1226,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
if (__a == __x.__alloc()) {
this->__begin_ = __x.__begin_;
this->__end_ = __x.__end_;
@@ -1260,7 +1256,7 @@ vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__il.size() > 0) {
__vallocate(__il.size());
@@ -1844,7 +1840,7 @@ private:
__storage_pointer __begin_;
size_type __size_;
- __compressed_pair<size_type, __storage_allocator> __cap_alloc_;
+ _LIBCPP_COMPRESSED_PAIR(size_type, __cap_, __storage_allocator, __alloc_);
public:
typedef __bit_reference<vector> reference;
@@ -1855,15 +1851,12 @@ public:
#endif
private:
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type& __cap() _NOEXCEPT { return __cap_alloc_.first(); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const size_type& __cap() const _NOEXCEPT {
- return __cap_alloc_.first();
- }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __storage_allocator& __alloc() _NOEXCEPT {
- return __cap_alloc_.second();
- }
+ // TODO: Remove these now redundant accessors
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type& __cap() _NOEXCEPT { return __cap_; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const size_type& __cap() const _NOEXCEPT { return __cap_; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __storage_allocator& __alloc() _NOEXCEPT { return __alloc_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const __storage_allocator& __alloc() const _NOEXCEPT {
- return __cap_alloc_.second();
+ return __alloc_;
}
static const unsigned __bits_per_word = static_cast<unsigned>(sizeof(__storage_type) * CHAR_BIT);
@@ -1926,7 +1919,7 @@ public:
#if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<bool> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -2331,7 +2324,7 @@ vector<bool, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel _
template <class _Allocator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector()
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {}
+ : __begin_(nullptr), __size_(0), __cap_(0) {}
template <class _Allocator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const allocator_type& __a)
@@ -2340,12 +2333,12 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocat
#else
_NOEXCEPT
#endif
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
}
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
+ : __begin_(nullptr), __size_(0), __cap_(0) {
if (__n > 0) {
__vallocate(__n);
__construct_at_end(__n, false);
@@ -2355,7 +2348,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n)
#if _LIBCPP_STD_VER >= 14
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
if (__n > 0) {
__vallocate(__n);
__construct_at_end(__n, false);
@@ -2365,7 +2358,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, co
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, const value_type& __x)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
+ : __begin_(nullptr), __size_(0), __cap_(0) {
if (__n > 0) {
__vallocate(__n);
__construct_at_end(__n, __x);
@@ -2375,7 +2368,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, co
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<bool, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
if (__n > 0) {
__vallocate(__n);
__construct_at_end(__n, __x);
@@ -2385,7 +2378,7 @@ vector<bool, _Allocator>::vector(size_type __n, const value_type& __x, const all
template <class _Allocator>
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
+ : __begin_(nullptr), __size_(0), __cap_(0) {
__init_with_sentinel(__first, __last);
}
@@ -2393,14 +2386,14 @@ template <class _Allocator>
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
__init_with_sentinel(__first, __last);
}
template <class _Allocator>
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
+ : __begin_(nullptr), __size_(0), __cap_(0) {
auto __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -2409,7 +2402,7 @@ template <class _Allocator>
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
auto __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -2418,7 +2411,7 @@ vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __la
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(initializer_list<value_type> __il)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
+ : __begin_(nullptr), __size_(0), __cap_(0) {
size_type __n = static_cast<size_type>(__il.size());
if (__n > 0) {
__vallocate(__n);
@@ -2429,7 +2422,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(initializer_list<
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(static_cast<__storage_allocator>(__a)) {
size_type __n = static_cast<size_type>(__il.size());
if (__n > 0) {
__vallocate(__n);
@@ -2443,7 +2436,8 @@ template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v)
: __begin_(nullptr),
__size_(0),
- __cap_alloc_(0, __storage_traits::select_on_container_copy_construction(__v.__alloc())) {
+ __cap_(0),
+ __alloc_(__storage_traits::select_on_container_copy_construction(__v.__alloc())) {
if (__v.size() > 0) {
__vallocate(__v.size());
__construct_at_end(__v.begin(), __v.end(), __v.size());
@@ -2452,7 +2446,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v, const allocator_type& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(__a) {
if (__v.size() > 0) {
__vallocate(__v.size());
__construct_at_end(__v.begin(), __v.end(), __v.size());
@@ -2484,7 +2478,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocat
#endif
: __begin_(__v.__begin_),
__size_(__v.__size_),
- __cap_alloc_(std::move(__v.__cap_alloc_)) {
+ __cap_(__v.__cap_),
+ __alloc_(std::move(__v.__alloc_)) {
__v.__begin_ = nullptr;
__v.__size_ = 0;
__v.__cap() = 0;
@@ -2493,7 +2488,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocat
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20
vector<bool, _Allocator>::vector(vector&& __v, const __type_identity_t<allocator_type>& __a)
- : __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) {
+ : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(__a) {
if (__a == allocator_type(__v.__alloc())) {
this->__begin_ = __v.__begin_;
this->__size_ = __v.__size_;
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/missing_hash_specialization.verify.cpp b/libcxx/test/libcxx/containers/unord/unord.set/missing_hash_specialization.verify.cpp
index f492b760edf26..f6d93c7e6ca57 100644
--- a/libcxx/test/libcxx/containers/unord/unord.set/missing_hash_specialization.verify.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.set/missing_hash_specialization.verify.cpp
@@ -48,11 +48,10 @@ int main(int, char**) {
using Set = std::unordered_set<VT>;
Set s; // expected-error at __hash_table:* {{the specified hash does not meet the Hash requirements}}
-
- // FIXME: It would be great to suppress the below diagnostic all together.
- // but for now it's sufficient that it appears last. However there is
- // currently no way to test the order diagnostics are issued.
- // expected-error@*:* {{call to implicitly-deleted default constructor of 'std::}}
+ // FIXME: It would be great to suppress the below diagnostic all together.
+ // but for now it's sufficient that it appears last. However there is
+ // currently no way to test the order diagnostics are issued.
+ // expected-error@*:* {{call to implicitly-deleted default constructor}}
}
{
using Set = std::unordered_set<int, BadHashNoCopy>;
diff --git a/libcxx/test/libcxx/memory/compressed_pair/compressed_pair.pass.cpp b/libcxx/test/libcxx/memory/compressed_pair/compressed_pair.pass.cpp
deleted file mode 100644
index 8bc890a208d0c..0000000000000
--- a/libcxx/test/libcxx/memory/compressed_pair/compressed_pair.pass.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include <assert.h>
-#include <memory>
-#include <new>
-
-#include "test_macros.h"
-
-typedef std::__compressed_pair<int, unsigned> IntPair;
-
-void test_constructor() {
- IntPair value;
- assert(value.first() == 0);
- assert(value.second() == 0);
-
- value.first() = 1;
- value.second() = 2;
- new (&value) IntPair;
- assert(value.first() == 0);
- assert(value.second() == 0);
-}
-
-void test_constructor_default_init() {
- IntPair value;
- value.first() = 1;
- value.second() = 2;
-
- new (&value) IntPair(std::__default_init_tag(), 3);
- assert(value.first() == 1);
- assert(value.second() == 3);
-
- new (&value) IntPair(4, std::__default_init_tag());
- assert(value.first() == 4);
- assert(value.second() == 3);
-
- new (&value) IntPair(std::__default_init_tag(), std::__default_init_tag());
- assert(value.first() == 4);
- assert(value.second() == 3);
-}
-
-int main(int, char**)
-{
- test_constructor();
- test_constructor_default_init();
- return 0;
-}
diff --git a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp b/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp
index 0af79eef4687a..9b90f1716f3b1 100644
--- a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp
+++ b/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp
@@ -18,6 +18,7 @@
#include <cassert>
#include <cstddef>
#include <memory>
+#include <tuple>
#include <type_traits>
#include <utility>
@@ -26,6 +27,44 @@
#include "test_macros.h"
+struct value_init_tag {};
+
+template <class T, int _Idx, bool CanBeEmptyBase = std::is_empty<T>::value && !std::__libcpp_is_final<T>::value>
+struct compressed_pair_elem {
+ explicit compressed_pair_elem(value_init_tag) : value_() {}
+
+ template <class U>
+ explicit compressed_pair_elem(U&& u) : value_(std::forward<U>(u)) {}
+
+ T& get() { return value_; }
+
+private:
+ T value_;
+};
+
+template <class T, int _Idx>
+struct compressed_pair_elem<T, _Idx, true> : private T {
+ explicit compressed_pair_elem(value_init_tag) : T() {}
+
+ template <class U>
+ explicit compressed_pair_elem(U&& u) : T(std::forward<U>(u)) {}
+
+ T& get() { return *this; }
+};
+
+template <class T1, class T2>
+class compressed_pair : private compressed_pair_elem<T1, 0>, private compressed_pair_elem<T2, 1> {
+public:
+ using Base1 = compressed_pair_elem<T1, 0>;
+ using Base2 = compressed_pair_elem<T2, 1>;
+
+ template <class U1, class U2>
+ explicit compressed_pair(U1&& t1, U2&& t2) : Base1(std::forward<U1>(t1)), Base2(std::forward<U2>(t2)) {}
+
+ T1& first() { return static_cast<Base1&>(*this).get(); }
+ T2& second() { return static_cast<Base2&>(*this).get(); }
+};
+
// This is the pre-C++20 implementation of the control block used by non-array
// std::allocate_shared and std::make_shared. We keep it here so that we can
// make sure our implementation is backwards compatible with it forever.
@@ -33,10 +72,8 @@
// Of course, the class and its methods were renamed, but the size and layout
// of the class should remain the same as the original implementation.
template <class T, class Alloc>
-struct OldEmplaceControlBlock
- : std::__shared_weak_count
-{
- explicit OldEmplaceControlBlock(Alloc a) : data_(std::move(a), std::__value_init_tag()) { }
+struct OldEmplaceControlBlock : std::__shared_weak_count {
+ explicit OldEmplaceControlBlock(Alloc a) : data_(std::move(a), value_init_tag()) {}
T* get_elem() noexcept { return std::addressof(data_.second()); }
Alloc* get_alloc() noexcept { return std::addressof(data_.first()); }
@@ -49,7 +86,7 @@ struct OldEmplaceControlBlock
// Not implemented
}
- std::__compressed_pair<Alloc, T> data_;
+ compressed_pair<Alloc, T> data_;
};
template <class T, template <class> class Alloc>
@@ -67,8 +104,8 @@ void test() {
// 1. Check the stored object
{
- char const* old_elem = reinterpret_cast<char const*>(old.get_elem());
- char const* new_elem = reinterpret_cast<char const*>(new_.__get_elem());
+ char const* old_elem = reinterpret_cast<char const*>(old.get_elem());
+ char const* new_elem = reinterpret_cast<char const*>(new_.__get_elem());
std::ptrdiff_t old_offset = old_elem - reinterpret_cast<char const*>(&old);
std::ptrdiff_t new_offset = new_elem - reinterpret_cast<char const*>(&new_);
assert(new_offset == old_offset && "offset of stored element changed");
@@ -76,8 +113,8 @@ void test() {
// 2. Check the allocator
{
- char const* old_alloc = reinterpret_cast<char const*>(old.get_alloc());
- char const* new_alloc = reinterpret_cast<char const*>(new_.__get_alloc());
+ char const* old_alloc = reinterpret_cast<char const*>(old.get_alloc());
+ char const* new_alloc = reinterpret_cast<char const*>(new_.__get_alloc());
std::ptrdiff_t old_offset = old_alloc - reinterpret_cast<char const*>(&old);
std::ptrdiff_t new_offset = new_alloc - reinterpret_cast<char const*>(&new_);
assert(new_offset == old_offset && "offset of allocator changed");
@@ -89,48 +126,64 @@ void test() {
}
// Object types to store in the control block
-struct TrivialEmptyType { };
-struct TrivialNonEmptyType { char c[11]; };
-struct FinalEmptyType final { };
+struct TrivialEmptyType {};
+
+struct TrivialNonEmptyType {
+ char c[11];
+};
+
+struct FinalEmptyType final {};
+
struct NonTrivialType {
char c[22];
- NonTrivialType() : c{'x'} { }
+ NonTrivialType() : c{'x'} {}
+};
+
+struct VirtualFunctionType {
+ virtual ~VirtualFunctionType() {}
};
// Allocator types
template <class T>
struct TrivialEmptyAlloc {
- using value_type = T;
+ using value_type = T;
TrivialEmptyAlloc() = default;
- template <class U> TrivialEmptyAlloc(TrivialEmptyAlloc<U>) { }
+ template <class U>
+ TrivialEmptyAlloc(TrivialEmptyAlloc<U>) {}
T* allocate(std::size_t) { return nullptr; }
- void deallocate(T*, std::size_t) { }
+ void deallocate(T*, std::size_t) {}
};
+
template <class T>
struct TrivialNonEmptyAlloc {
char storage[77];
- using value_type = T;
+ using value_type = T;
TrivialNonEmptyAlloc() = default;
- template <class U> TrivialNonEmptyAlloc(TrivialNonEmptyAlloc<U>) { }
+ template <class U>
+ TrivialNonEmptyAlloc(TrivialNonEmptyAlloc<U>) {}
T* allocate(std::size_t) { return nullptr; }
- void deallocate(T*, std::size_t) { }
+ void deallocate(T*, std::size_t) {}
};
+
template <class T>
struct FinalEmptyAlloc final {
- using value_type = T;
+ using value_type = T;
FinalEmptyAlloc() = default;
- template <class U> FinalEmptyAlloc(FinalEmptyAlloc<U>) { }
+ template <class U>
+ FinalEmptyAlloc(FinalEmptyAlloc<U>) {}
T* allocate(std::size_t) { return nullptr; }
- void deallocate(T*, std::size_t) { }
+ void deallocate(T*, std::size_t) {}
};
+
template <class T>
struct NonTrivialAlloc {
char storage[88];
using value_type = T;
- NonTrivialAlloc() { }
- template <class U> NonTrivialAlloc(NonTrivialAlloc<U>) { }
+ NonTrivialAlloc() {}
+ template <class U>
+ NonTrivialAlloc(NonTrivialAlloc<U>) {}
T* allocate(std::size_t) { return nullptr; }
- void deallocate(T*, std::size_t) { }
+ void deallocate(T*, std::size_t) {}
};
int main(int, char**) {
@@ -145,15 +198,19 @@ int main(int, char**) {
test<TrivialNonEmptyType, NonTrivialAlloc>();
test<FinalEmptyType, TrivialEmptyAlloc>();
- test<FinalEmptyType, TrivialNonEmptyAlloc>();
- test<FinalEmptyType, FinalEmptyAlloc>();
- test<FinalEmptyType, NonTrivialAlloc>();
+ // FinalEmptyType combined with TrivialNonEmptyAlloc, FinalEmptyAlloc or NonTrivialAlloc is known to have an ABI break
+ // between LLVM 18 and LLVM 19. It's been deemed not severe enough to cause actual breakage.
test<NonTrivialType, TrivialEmptyAlloc>();
test<NonTrivialType, TrivialNonEmptyAlloc>();
test<NonTrivialType, FinalEmptyAlloc>();
test<NonTrivialType, NonTrivialAlloc>();
+ test<VirtualFunctionType, TrivialEmptyAlloc>();
+ test<VirtualFunctionType, TrivialNonEmptyAlloc>();
+ test<VirtualFunctionType, FinalEmptyAlloc>();
+ test<VirtualFunctionType, NonTrivialAlloc>();
+
// Test a few real world types just to make sure we didn't mess up badly somehow
test<std::string, std::allocator>();
test<int, std::allocator>();
More information about the libcxx-commits
mailing list