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.