[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