Skip to content

Commit 1a5f8e4

Browse files
committed
[libc++] Annotate the data member of variant with no_unique_address attribute.
This allows clients to reuse tail padding after the index (if any), by applying [[no_unique_address]] to variant fields.
1 parent f2b8539 commit 1a5f8e4

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

libcxx/include/__configuration/abi.h

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
// Use the smallest possible integer type to represent the index of the variant.
5858
// Previously libc++ used "unsigned int" exclusively.
5959
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
60+
// Allow to reuse tail padding after the index of the variant with [[no_unique_address]] attribute.
61+
# define _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
6062
// Unstable attempt to provide a more optimized std::function
6163
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
6264
// All the regex constants must be distinct and nonzero.

libcxx/include/variant

+5-1
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,11 @@ public:
13191319
# endif
13201320

13211321
private:
1322-
__variant_detail::__impl<_Types...> __impl_;
1322+
# ifdef _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
1323+
_LIBCPP_NO_UNIQUE_ADDRESS
1324+
# endif // _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
1325+
__variant_detail::__impl<_Types...>
1326+
__impl_;
13231327

13241328
friend struct __variant_detail::__access::__variant;
13251329
friend struct __variant_detail::__visitation::__variant;

libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ struct type_with_index {
7070
#endif
7171
};
7272

73+
struct alignas(16) A16 {};
74+
struct VariantWithNoUniqueAddress {
75+
TEST_NO_UNIQUE_ADDRESS std::variant<A16> a;
76+
bool b;
77+
};
78+
struct VariantWithoutNoUniqueAddress {
79+
std::variant<A16> a;
80+
bool b;
81+
};
82+
constexpr bool ExpectSmallerSizeWithNoUniqueAddress =
83+
#ifdef _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
84+
true;
85+
#else
86+
false;
87+
#endif
88+
7389
int main(int, char**) {
7490
test_index_type<unsigned char>();
7591
// This won't compile due to template depth issues.
@@ -84,5 +100,8 @@ int main(int, char**) {
84100
static_assert(sizeof(std::variant<char, int, long>) == sizeof(type_with_index<long>));
85101
static_assert(sizeof(std::variant<std::size_t, std::size_t, std::size_t>) == sizeof(type_with_index<std::size_t>));
86102

103+
static_assert((sizeof(VariantWithNoUniqueAddress) < sizeof(VariantWithoutNoUniqueAddress)) ==
104+
ExpectSmallerSizeWithNoUniqueAddress);
105+
87106
return 0;
88107
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++17
10+
11+
// <variant>
12+
13+
#include <cassert>
14+
#include <variant>
15+
16+
#include "test_macros.h"
17+
18+
struct S {
19+
TEST_NO_UNIQUE_ADDRESS std::variant<int, void*> a;
20+
bool b;
21+
};
22+
23+
TEST_CONSTEXPR_CXX20 bool test() {
24+
S x{{}, true};
25+
x.a.emplace<0>();
26+
x.a.emplace<1>();
27+
return x.b;
28+
}
29+
30+
int main() {
31+
assert(test());
32+
#if TEST_STD_VER >= 20
33+
static_assert(test());
34+
#endif
35+
}

0 commit comments

Comments
 (0)