[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
Sat May 3 05:13:33 PDT 2025
huixie90 wrote:
> I am not sure if you are aware of the bug that we had in `std::expected`, where we applied `no_unique_address` to the union. The bug was that, every time we `emplace`, the `construct_at` will **zero initialise** the tail padding of the union, erasing anything that lives in the tail padding of the union of `T` or `Err`, including the discriminator and any other user data if the user chose to `no_unique_address` of the whole `expected`.
>
> We ended up have to ABI break to fix `expected`. (only conditionally apply `no_unique_address` and do not allow user's type to fit into's `union`'s tail padding). We only allow the user data to reuse padding when the discriminator is not in the tail padding of the `union` (meaning the `emplace` will not touch the user data)
>
> I think this `variant` case is quite similar and just wanted to double check if you have thought about this.
>
> so to test this case, we want something that is big enough to fit our index type into the tail padding of T
>
> ```c++
> struct F {
> F(){} // to make it not a c-struct
> long double c{};
> bool b{};
> };
>
> struct S {
> [[no_unique_address]] std::variant<int, F> v;
> bool b;
> }
>
>
> S s{};
> s.b = true;
> s.v.emplace<F>(......);
>
> assert(s.b)
> ```
so in summary, i think to have an optimal solution, we want the layout to be something like this
```cpp
struct repr {
[[no_unique_address]] the_recursive_union<...> t;
index_t index;
};
// If index can fit into the tail padding of the union of variant, we want index to be inside the tail padding, but not the user data
class variant {
repr repr_;
};
// if index cannot fit into the tail padding, we can allow user to reuse the tail padding after the index, because it is not going to be overwritten
class variant {
[[no_unique_address]] repr repr_;
};
```
https://github.com/llvm/llvm-project/pull/137783
More information about the libcxx-commits
mailing list