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.

Reply via email to