[libcxx-commits] [libcxx] [libc++] Annotate the data member of variant with no_unique_address (PR #137783)
Alex Aktsipetrov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 29 07:48:30 PDT 2025
https://github.com/gizmondo updated https://github.com/llvm/llvm-project/pull/137783
>From e457f6a351303011a5193011095c87425da30580 Mon Sep 17 00:00:00 2001
From: Alex Aktsipetrov <akts at google.com>
Date: Tue, 29 Apr 2025 12:20:15 +0200
Subject: [PATCH] [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.
---
libcxx/include/__configuration/abi.h | 2 ++
libcxx/include/variant | 6 +++-
.../variant.variant/variant_size.pass.cpp | 19 ++++++++++
..._robust_against_no_unique_address.pass.cpp | 35 +++++++++++++++++++
4 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 libcxx/test/std/utilities/variant/variant.variant/variant_robust_against_no_unique_address.pass.cpp
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 01a4a4c023983..f867fb12206a7 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -57,6 +57,8 @@
// Use the smallest possible integer type to represent the index of the variant.
// Previously libc++ used "unsigned int" exclusively.
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
+// Allow to reuse tail padding after the index of the variant with [[no_unique_address]] attribute.
+# define _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
// Unstable attempt to provide a more optimized std::function
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
// All the regex constants must be distinct and nonzero.
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 74a464d27ead4..b4f0856ebb17f 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1319,7 +1319,11 @@ public:
# endif
private:
- __variant_detail::__impl<_Types...> __impl_;
+# ifdef _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
+ _LIBCPP_NO_UNIQUE_ADDRESS
+# endif // _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
+ __variant_detail::__impl<_Types...>
+ __impl_;
friend struct __variant_detail::__access::__variant;
friend struct __variant_detail::__visitation::__variant;
diff --git a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
index 2f1ea8bffb479..62abcd364c7ac 100644
--- a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
+++ b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
@@ -70,6 +70,22 @@ struct type_with_index {
#endif
};
+struct alignas(16) A16 {};
+struct VariantWithNoUniqueAddress {
+ TEST_NO_UNIQUE_ADDRESS std::variant<A16> a;
+ bool b;
+};
+struct VariantWithoutNoUniqueAddress {
+ std::variant<A16> a;
+ bool b;
+};
+constexpr bool ExpectSmallerSizeWithNoUniqueAddress =
+#ifdef _LIBCPP_ABI_VARIANT_NO_UNIQUE_ADDRESS_OPTIMIZATION
+ true;
+#else
+ false;
+#endif
+
int main(int, char**) {
test_index_type<unsigned char>();
// This won't compile due to template depth issues.
@@ -84,5 +100,8 @@ int main(int, char**) {
static_assert(sizeof(std::variant<char, int, long>) == sizeof(type_with_index<long>));
static_assert(sizeof(std::variant<std::size_t, std::size_t, std::size_t>) == sizeof(type_with_index<std::size_t>));
+ static_assert((sizeof(VariantWithNoUniqueAddress) < sizeof(VariantWithoutNoUniqueAddress)) ==
+ ExpectSmallerSizeWithNoUniqueAddress);
+
return 0;
}
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant_robust_against_no_unique_address.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant_robust_against_no_unique_address.pass.cpp
new file mode 100644
index 0000000000000..06f598aa40329
--- /dev/null
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant_robust_against_no_unique_address.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// <variant>
+
+#include <cassert>
+#include <variant>
+
+#include "test_macros.h"
+
+struct S {
+ TEST_NO_UNIQUE_ADDRESS std::variant<int, void*> a;
+ bool b;
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ S x{{}, true};
+ x.a.emplace<0>();
+ x.a.emplace<1>();
+ return x.b;
+}
+
+int main() {
+ assert(test());
+#if TEST_STD_VER >= 20
+ static_assert(test());
+#endif
+}
More information about the libcxx-commits
mailing list