c++structabilibc++

Is [[__no_unique_address__]] applied to second members in this tail padding optimization check in libc++ redundant?


In the libc++ implementation of std::expected, there is this helper variable template:

// This function returns whether the type `_Second` can be stuffed into the tail padding
// of the `_First` type if both of them are given `[[no_unique_address]]`.
template <class _First, class _Second>
inline constexpr bool __fits_in_tail_padding = []() {
  struct __x {
    _LIBCPP_NO_UNIQUE_ADDRESS _First __first;
    _LIBCPP_NO_UNIQUE_ADDRESS _Second __second;
  };
  return sizeof(__x) == sizeof(_First);
}();

_LIBCPP_NO_UNIQUE_ADDRESS is defined as:

#  if __has_cpp_attribute(msvc::no_unique_address)
// MSVC implements [[no_unique_address]] as a silent no-op currently.
// (If/when MSVC breaks its C++ ABI, it will be changed to work as intended.)
// However, MSVC implements [[msvc::no_unique_address]] which does what
// [[no_unique_address]] is supposed to do, in general.
#    define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#  else
#    define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]]
#  endif

In my understanding, it is the __second that can be inserted into tail padding of __first, not the other way around. In that case, is _LIBCPP_NO_UNIQUE_ADDRESS applied to __second redundant?

The Itanium ABI defines a concept called "POD for the purpose of layout", which prevents compilers from utilizing tail padding of POD structs. However, since __x would already have potentially overlapping members with only __first being marked as _LIBCPP_NO_UNIQUE_ADDRESS, it wouldn't be considered "POD for the purpose of layout" even without _LIBCPP_NO_UNIQUE_ADDRESS applied to __second.


Solution

  • It is not redundant, as the behavior differs depending on whether or not the attribute is applied to __second.

    In particular, when both __first and __second are annotated with _LIBCPP_NO_UNIQUE_ADDRESS, __fits_in_tail_padding<int, Empty> evaluates to true (Empty here being struct Empty {};), whereas if only __first is annotated, it evaluates to false.

    The reason is that [[no_unique_address]] allows both reuse of tail padding and elision of empty classes. In the case of empty class elision, the attribute must be applied to a member whose type is a potentially empty class - in this case, __second.