Correctly handle fields with virtual bases containing empty subobjects.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105628 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anders Carlsson 2010-06-08 19:09:24 +00:00
Родитель 55d7d36f48
Коммит 45f5b54d67
2 изменённых файлов: 54 добавлений и 2 удалений

Просмотреть файл

@ -201,7 +201,7 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
ClassVectorTy& Classes = EmptyClassOffsets[Offset];
assert(std::find(Classes.begin(), Classes.end(), RD) == Classes.end() &&
"Duplicate empty class detected!");
Classes.push_back(RD);
// Update the empty class offset.
@ -332,6 +332,19 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
return false;
}
if (RD == Class) {
// This is the most derived class, traverse virtual bases as well.
for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
E = RD->vbases_end(); I != E; ++I) {
const CXXRecordDecl *VBaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
return false;
}
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
@ -402,6 +415,7 @@ EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) {
void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
uint64_t Offset) {
AddSubobjectAtOffset(RD, Offset);
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@ -419,6 +433,18 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
}
if (RD == Class) {
// This is the most derived class, traverse virtual bases as well.
for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
E = RD->vbases_end(); I != E; ++I) {
const CXXRecordDecl *VBaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
}
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();

Просмотреть файл

@ -117,4 +117,30 @@ struct B { A a; };
struct C : B, Empty { };
SA(0, sizeof(C) == 2);
}
}
namespace Test5 {
// Test that B::Empty isn't laid out at offset 0.
struct Empty { };
struct Field : virtual Empty { };
struct A {
Field f;
};
struct B : A, Empty { };
SA(0, sizeof(B) == 16);
}
namespace Test6 {
// Test that B::A isn't laid out at offset 0.
struct Empty { };
struct Field : virtual Empty { };
struct A {
Field f;
};
struct B : Empty, A { };
SA(0, sizeof(B) == 16);
}