зеркало из https://github.com/microsoft/clang.git
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:
Родитель
55d7d36f48
Коммит
45f5b54d67
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче