Skip to content

Commit 5d0b99d

Browse files
committed
[libc++] Replace __compressed_pair with [[no_unique_address]]
1 parent e6ec366 commit 5d0b99d

File tree

21 files changed

+652
-600
lines changed

21 files changed

+652
-600
lines changed

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ ABI Affecting Changes
143143
``random_device`` could throw a ``system_error`` with this value. It now
144144
throws ``ENOMSG``.
145145

146+
- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``. This change results in
147+
empty final types being placed at the beginning of the object instead of where the beginning of the
148+
``__compressed_pair`` subobject was. This is only observable by checking the address of the subobject.
146149

147150
Build System Changes
148151
--------------------

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
===========================================
2+
Libc++ 20.0.0 (In-Progress) Release Notes
3+
===========================================
4+
5+
.. contents::
6+
:local:
7+
:depth: 2
8+
9+
Written by the `Libc++ Team <https://libcxx.llvm.org>`_
10+
11+
.. warning::
12+
13+
These are in-progress notes for the upcoming libc++ 20.0.0 release.
14+
Release notes for previous releases can be found on
15+
`the Download Page <https://releases.llvm.org/download.html>`_.
16+
17+
Introduction
18+
============
19+
20+
This document contains the release notes for the libc++ C++ Standard Library,
21+
part of the LLVM Compiler Infrastructure, release 19.0.0. Here we describe the
22+
status of libc++ in some detail, including major improvements from the previous
23+
release and new feature work. For the general LLVM release notes, see `the LLVM
24+
documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM releases may
25+
be downloaded from the `LLVM releases web site <https://llvm.org/releases/>`_.
26+
27+
For more information about libc++, please see the `Libc++ Web Site
28+
<https://libcxx.llvm.org>`_ or the `LLVM Web Site <https://llvm.org>`_.
29+
30+
Note that if you are reading this file from a Git checkout or the
31+
main Libc++ web page, this document applies to the *next* release, not
32+
the current one. To see the release notes for a specific release, please
33+
see the `releases page <https://llvm.org/releases/>`_.
34+
35+
What's New in Libc++ 20.0.0?
36+
==============================
37+
38+
Implemented Papers
39+
------------------
40+
41+
Improvements and New Features
42+
-----------------------------
43+
44+
- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``, resulting in reduced
45+
compile times and smaller debug information as well as better code gen if optimizations are disabled.
46+
47+
Deprecations and Removals
48+
-------------------------
49+
50+
- TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable and the ``_LIBCPP_ENABLE_ASSERTIONS`` macro that were used to
51+
enable the safe mode will be removed in LLVM 20.
52+
53+
Upcoming Deprecations and Removals
54+
----------------------------------
55+
56+
LLVM 21
57+
~~~~~~~
58+
TODO
59+
60+
61+
ABI Affecting Changes
62+
---------------------
63+
64+
- The internal structure ``__compressed_pair`` has been replaced with ``[[no_unique_address]]``. This change results in
65+
empty final types being placed at the beginning of the object instead of where the beginning of the
66+
``__compressed_pair`` subobject was. This is only observable by checking the address of the subobject.
67+
68+
Build System Changes
69+
--------------------
70+
71+
- The ``LIBCXX_EXECUTOR`` and ``LIBCXXABI_EXECUTOR`` CMake variables have been removed. Please
72+
set ``LIBCXX_TEST_PARAMS`` to ``executor=<...>`` instead.
73+
74+
- The Cmake variable ``LIBCXX_ENABLE_CLANG_TIDY`` has been removed. The build system has been changed
75+
to automatically detect the presence of ``clang-tidy`` and the required ``Clang`` libraries.
76+
77+
- The CMake options ``LIBCXX_INSTALL_MODULES`` now defaults to ``ON``.

libcxx/include/__config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
3333
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
34+
# define _LIBCPP_CONCAT3(X, Y, Z) _LIBCPP_CONCAT(X, _LIBCPP_CONCAT(Y, Z))
3435

3536
# if __STDC_HOSTED__ == 0
3637
# define _LIBCPP_FREESTANDING

libcxx/include/__configuration/abi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@
9191
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
9292
// Dont' add an inline namespace for `std::filesystem`
9393
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
94+
// Historically, libc++ used a type called `__compressed_pair` to reduce storage need in cases of empty types (e.g. an
95+
// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons
96+
// we had to add artificial padding in a few places.
97+
//
98+
// This setting disables the addition of such artificial padding, leading to a more optimal
99+
// representation for several types.
100+
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
94101
#elif _LIBCPP_ABI_VERSION == 1
95102
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
96103
// Enable compiling copies of now inline methods into the dylib to support

libcxx/include/__functional/function.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,45 +143,46 @@ class __default_alloc_func;
143143

144144
template <class _Fp, class _Ap, class _Rp, class... _ArgTypes>
145145
class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
146-
__compressed_pair<_Fp, _Ap> __f_;
146+
_LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_);
147147

148148
public:
149149
typedef _LIBCPP_NODEBUG _Fp _Target;
150150
typedef _LIBCPP_NODEBUG _Ap _Alloc;
151151

152-
_LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_.first(); }
152+
_LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __func_; }
153153

154154
// WIN32 APIs may define __allocator, so use __get_allocator instead.
155-
_LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __f_.second(); }
155+
_LIBCPP_HIDE_FROM_ABI const _Alloc& __get_allocator() const { return __alloc_; }
156156

157-
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f)
158-
: __f_(piecewise_construct, std::forward_as_tuple(std::move(__f)), std::forward_as_tuple()) {}
157+
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f) : __func_(std::move(__f)), __alloc_() {}
159158

160-
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a)
161-
: __f_(piecewise_construct, std::forward_as_tuple(__f), std::forward_as_tuple(__a)) {}
159+
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, const _Alloc& __a) : __func_(__f), __alloc_(__a) {}
162160

163161
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(const _Target& __f, _Alloc&& __a)
164-
: __f_(piecewise_construct, std::forward_as_tuple(__f), std::forward_as_tuple(std::move(__a))) {}
162+
: __func_(__f), __alloc_(std::move(__a)) {}
165163

166164
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a)
167-
: __f_(piecewise_construct, std::forward_as_tuple(std::move(__f)), std::forward_as_tuple(std::move(__a))) {}
165+
: __func_(std::move(__f)), __alloc_(std::move(__a)) {}
168166

169167
_LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
170168
typedef __invoke_void_return_wrapper<_Rp> _Invoker;
171-
return _Invoker::__call(__f_.first(), std::forward<_ArgTypes>(__arg)...);
169+
return _Invoker::__call(__func_, std::forward<_ArgTypes>(__arg)...);
172170
}
173171

174172
_LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const {
175173
typedef allocator_traits<_Alloc> __alloc_traits;
176174
typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA;
177-
_AA __a(__f_.second());
175+
_AA __a(__alloc_);
178176
typedef __allocator_destructor<_AA> _Dp;
179177
unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
180-
::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a));
178+
::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a));
181179
return __hold.release();
182180
}
183181

184-
_LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); }
182+
_LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT {
183+
__func_.~_Fp();
184+
__alloc_.~_Alloc();
185+
}
185186

186187
_LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) {
187188
typedef allocator_traits<_Alloc> __alloc_traits;

0 commit comments

Comments
 (0)