[libcxx-commits] [libcxx] [libc++] Annotate the data member of variant with no_unique_address (PR #137783)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 29 03:33:57 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Alex Aktsipetrov (gizmondo)

<details>
<summary>Changes</summary>

This allows clients to reuse tail padding after the index (if any), by applying no_unique_address attribute to their variant fields. 

E.g. the following struct would have smaller size.
```
struct S {
    [[no_unique_address]] std::variant<int, string> a;
    bool b;
};
```
Currently no_unique_address in this code doesn't do anything, so this is an ABI break.



---
Full diff: https://github.com/llvm/llvm-project/pull/137783.diff


3 Files Affected:

- (modified) libcxx/include/__configuration/abi.h (+2) 
- (modified) libcxx/include/variant (+5-1) 
- (modified) libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp (+19) 


``````````diff
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;
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/137783


More information about the libcxx-commits mailing list