Object layout question (possible bug?)

I was investigating a difference in struct layout between clang and other compilers we use. We have many structs that inherit from an empty base struct (“Object”). The first member of these structs is usually at offset 0; but in clang, one of them has its first member at offset 4. It turns out that this happens when that first member is also a subclass of Object.

That led me to some language lawyer research into the EBO and standard layout rules of C++11; maybe not coincidentally, there is a new-ish standard layout rule which says “6. has no base classes of the same type as the first non-static data member” (ref: http://en.cppreference.com/w/cpp/types/is_standard_layout). Confusingly, not all C++11 reference sites quote that rule 6. Also confusingly, clang reports that my oddball struct is in fact “standard layout”

My questions are:

  • Is it a bug that clang puts my struct’s first member at offset 0?
  • Is it a bug that clang claims my struct __is_standard_layout()?
  • (Perhaps also: should I instead bring this up on cfe-dev?)

Thanks for any insight! My test case follows.

p

// Compiled with latest Xcode’s clang, using
// clang foo.cc
// clang -cc1 -fdump-record-layouts foo.cc
#define cassert(expr) typedef char failed[(expr)?1:-1]

class Object {};
struct RsaLight : public Object {
float data;
};

struct Weather : public Object {
RsaLight m_first;
float data;
};

class Object2 {};
struct Weather2 : public Object2 {
RsaLight m_first;
float data;
};

int main(int argc, char** argv) {
// Q1: Should this assert actually fail?
cassert(__is_standard_layout(Weather));
// Q2: Should this offsetof actually be 0?
cassert(__builtin_offsetof(Weather, m_first) == 4);

cassert(__is_standard_layout(Weather2));
cassert(__builtin_offsetof(Weather2, m_first) == 0);

return sizeof(Weather) + sizeof(Weather2);
}