[cfe-commits] r105628 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp test/SemaCXX/empty-class-layout.cpp
Anders Carlsson
andersca at mac.com
Tue Jun 8 12:09:24 PDT 2010
Author: andersca
Date: Tue Jun 8 14:09:24 2010
New Revision: 105628
URL: http://llvm.org/viewvc/llvm-project?rev=105628&view=rev
Log:
Correctly handle fields with virtual bases containing empty subobjects.
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/test/SemaCXX/empty-class-layout.cpp
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=105628&r1=105627&r2=105628&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Tue Jun 8 14:09:24 2010
@@ -201,7 +201,7 @@
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 @@
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 @@
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 @@
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();
Modified: cfe/trunk/test/SemaCXX/empty-class-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/empty-class-layout.cpp?rev=105628&r1=105627&r2=105628&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/empty-class-layout.cpp (original)
+++ cfe/trunk/test/SemaCXX/empty-class-layout.cpp Tue Jun 8 14:09:24 2010
@@ -117,4 +117,30 @@
struct C : B, Empty { };
SA(0, sizeof(C) == 2);
-}
\ No newline at end of file
+}
+
+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);
+
+}
More information about the cfe-commits
mailing list