Skip to content

Commit 4807741

Browse files
committed
[libc++] Replace __compressed_pair with [[no_unique_address]]
1 parent bbd6a2d commit 4807741

File tree

20 files changed

+655
-605
lines changed

20 files changed

+655
-605
lines changed

Diff for: libcxx/docs/ReleaseNotes/19.rst

+3
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
--------------------

Diff for: libcxx/docs/ReleaseNotes/20.rst

+77
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``.

Diff for: libcxx/include/__config

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
5757
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
58+
# define _LIBCPP_CONCAT3(X, Y, Z) _LIBCPP_CONCAT(X, _LIBCPP_CONCAT(Y, Z))
5859

5960
# if __STDC_HOSTED__ == 0
6061
# define _LIBCPP_FREESTANDING
@@ -166,6 +167,13 @@
166167
// requires code not to make these assumptions.
167168
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
168169
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
170+
// Historically, libc++ used a type called `__compressed_pair` to reduce storage need in cases of empty types (e.g. an
171+
// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons
172+
// we had to add artificial padding in a few places.
173+
//
174+
// This setting disables the addition of such artificial padding, leading to a more optimal
175+
// representation for several types.
176+
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
169177
# elif _LIBCPP_ABI_VERSION == 1
170178
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
171179
// Enable compiling copies of now inline methods into the dylib to support

Diff for: libcxx/include/__functional/function.h

+14-13
Original file line numberDiff line numberDiff line change
@@ -144,45 +144,46 @@ class __default_alloc_func;
144144

145145
template <class _Fp, class _Ap, class _Rp, class... _ArgTypes>
146146
class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
147-
__compressed_pair<_Fp, _Ap> __f_;
147+
_LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Ap, __alloc_);
148148

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

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

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

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

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

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

167165
_LIBCPP_HIDE_FROM_ABI explicit __alloc_func(_Target&& __f, _Alloc&& __a)
168-
: __f_(piecewise_construct, std::forward_as_tuple(std::move(__f)), std::forward_as_tuple(std::move(__a))) {}
166+
: __func_(std::move(__f)), __alloc_(std::move(__a)) {}
169167

170168
_LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
171169
typedef __invoke_void_return_wrapper<_Rp> _Invoker;
172-
return _Invoker::__call(__f_.first(), std::forward<_ArgTypes>(__arg)...);
170+
return _Invoker::__call(__func_, std::forward<_ArgTypes>(__arg)...);
173171
}
174172

175173
_LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const {
176174
typedef allocator_traits<_Alloc> __alloc_traits;
177175
typedef __rebind_alloc<__alloc_traits, __alloc_func> _AA;
178-
_AA __a(__f_.second());
176+
_AA __a(__alloc_);
179177
typedef __allocator_destructor<_AA> _Dp;
180178
unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
181-
::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a));
179+
::new ((void*)__hold.get()) __alloc_func(__func_, _Alloc(__a));
182180
return __hold.release();
183181
}
184182

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

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

0 commit comments

Comments
 (0)