https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104419
Bug ID: 104419
Summary: [[no_unique_address]] interaction with
is_standard_layout
Product: gcc
Version: 11.2.1
Status: UNCONFIRMED
Keywords: ABI
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
GCC disagrees with Clang and MSVC in this example (reduced from our std::tuple,
and affecting std::unique_ptr):
template<typename T, bool = __is_empty(T)> struct node;
#ifdef USE_EBO
template<typename T> struct node<T, true> : T
{ };
#else
template<typename T> struct node<T, true>
{
[[no_unique_address]] T t;
};
#endif
template<typename T> struct node<T, false>
{
T t;
};
template<typename... T> struct tuple;
template<typename T>
struct tuple<T> : node<T> { };
template<typename T, typename U>
struct tuple<T, U> : tuple<U>, node<T>
{ };
struct empty {};
static_assert( sizeof(tuple<int, empty>) == sizeof(int), "" );
static_assert( __is_standard_layout(tuple<int>), "");
static_assert( __is_standard_layout(tuple<empty>), "");
static_assert( __is_standard_layout(tuple<int, empty>), ""); // Clang fails
template<typename... T> struct tuple2;
template<typename T, typename U>
struct tuple2<T, U> : node<U>, node<T>
{ };
static_assert( sizeof(tuple2<int, empty>) == sizeof(int), "" );
// GCC and Clang agree for this type (with no recursive inheritance)
static_assert( ! __is_standard_layout(tuple2<int, empty>), "");
If USE_EBO is defined, everybody agrees tuple<int, empty> is standard layout.
But when replacing EBO with [[no_unique_address]] other compilers say it's no
longer standard layout. If they're right, that's a problem for our std::tuple
(as it means the change to use [[no_unique_address]] in std::tuple affected its
ABI).
It seems to me that we should be able to replace EBO with [[no_unique_address]]
(that was the whole point of it), which would support GCC's interpretation. But
if that's the case, I'm not sure why tuple2<int, empty> isn't standard layout,
even for GCC.