C++ Logo

std-discussion

Advanced search

Layout compatible classes involving [[no_unique_address]] in the Itanium ABI

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Tue, 13 Oct 2020 19:09:49 +0100
Hi all,

Consider the following example:

#include <type_traits>
#include <cstddef>

class A1 {
    private:
    int i;
    char ch;
};

class B1 {
    public:
    [[no_unique_address]] A1 a;
    char ch;
};

static_assert(std::is_standard_layout_v<B1>);

class A2 {
    public:
    int i;
    char ch;
};

class B2 {
    public:
    [[no_unique_address]] A2 b2;
    char ch;
};

static_assert(std::is_standard_layout_v<B1>);
static_assert(offsetof(B1, ch) != offsetof(B2, ch));

Godbolt: https://godbolt.org/z/1o91bE

Following the standard wording A1 and A2 are layout compatible [1].
Similarly B1 and B2 are layout compatible. However the ch member in B1
has different offset than the ch member in B2.

In the Itanium ABI A1 is not POD for the purpose of layout while A2 is,
this affects the offset of the ch member.

Two possible directions to fix this:

* Modify the standard to disallow [[no_unique_address]] non-empty
  non-static data members to be part of a common initial sequence (or
  maybe only allow as the last element of a common initial sequence).
* Modify the ABI to disable overlapping of [[no_unique_address]]
  non-empty data members in standard-layout classes.

Personally I would prefer the first option of these two.

I also submitted an issue here:
https://github.com/itanium-cxx-abi/cxx-abi/issues/108

[1] https://eel.is/c++draft/class#mem.general-22

Regards,
Lénárd Szolnoki

Received on 2020-10-13 13:09:57