Essentially it’s just about importing a type with a single base class with member fields. There isn't anything problematic I ran into with this per-se, but it was a discrepancy I noticed while working on a different issue.
Setup:
// lib.h
class Base {
void* Field;
};
class Derived : Base {};
struct Foo {
Derived d;
};
// main.cpp
#include "lib.h"
int main() {
Foo f;
return 0;
}
Note that both class Derived and class Foo don’t have standard_layout set in its DefinitionData despite class Base having it set.
According to the standard, a standard-layout class is allowed to have a single base class with member fields (e.g., https://godbolt.org/z/a467evfdx). This is codified in RecordDecl::setBases as follows:
…
// C++2a [class]p7:
// A standard-layout class is a class that:
// [...]
// -- has all non-static data members and bit-fields in the class and
// its base classes first declared in the same class
if (BaseClassDecl->data().HasBasesWithFields ||
!BaseClassDecl->field_empty()) {
if (data().HasBasesWithFields) {
data().IsStandardLayout = false;
}
data().HasBasesWithFields = true;
}
…
When we're asked to complete Foo we call into DWARFASTParserClang::CompleteRecordType and then TypeSystemClang::TransferBaseClasses which calls CXXRecordDecl::setBases.
When we then import the definition into the scratch AST (see ASTNodeImporter::ImportDefinition), we do:
So now the To decl has HasBasesWithFields set going into CXXRecordDecl::setBases; this unsets IsStandardLayout because we mistakenly claimed that To has more than one base class with members.
Actually this seems like an ASTImporter bug. Running -ast-merge on the examples results in an AST doesn’t correctly attach the standard_layout attribute to Derived and Foo.
Essentially it’s just about importing a type with a single base class with member fields. There isn't anything problematic I ran into with this per-se, but it was a discrepancy I noticed while working on a different issue.
Setup:
This will print:
Note that both
class Derived
andclass Foo
don’t havestandard_layout
set in its DefinitionData despiteclass Base
having it set.According to the standard, a standard-layout class is allowed to have a single base class with member fields (e.g., https://godbolt.org/z/a467evfdx). This is codified in
RecordDecl::setBases
as follows:When we're asked to complete
Foo
we call intoDWARFASTParserClang::CompleteRecordType
and thenTypeSystemClang::TransferBaseClasses
which callsCXXRecordDecl::setBases
.When we then import the definition into the scratch AST (see
ASTNodeImporter::ImportDefinition
), we do:So now the
To
decl hasHasBasesWithFields
set going intoCXXRecordDecl::setBases
; this unsetsIsStandardLayout
because we mistakenly claimed thatTo
has more than one base class with members.