aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-09-24 03:22:10 +0000
committerAnders Carlsson <andersca@mac.com>2009-09-24 03:22:10 +0000
commit1345bd2b093e78620c32f5148b1279ed290188e8 (patch)
treed75379302c138c3bdf4b5763b26bb826657d004a
parent9606149722bedfc48fc56cafc58de1139aef481d (diff)
More work on empty classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82679 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp31
-rw-r--r--test/SemaCXX/empty-class-layout.cpp12
2 files changed, 35 insertions, 8 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 78598b7956..062ce4f5bc 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -221,30 +221,45 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
uint64_t Offset) const {
- // FIXME: Implement.
+ // Look for an empty class with the same type at the same offset.
+ for (EmptyClassOffsetsTy::const_iterator I =
+ EmptyClassOffsets.lower_bound(Offset),
+ E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) {
+
+ if (I->second == RD)
+ return false;
+ }
+
+ // FIXME: Bases and fields.
return true;
}
void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
uint64_t Offset) {
- // FIXME: Implement.
+ if (RD->isEmpty())
+ EmptyClassOffsets.insert(std::make_pair(Offset, RD));
+
+ // FIXME: Update bases and fields.
}
uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
- if (!Bases.empty()) {
- assert(BaseInfo.getDataSize() > 0 &&
- "FIXME: Handle empty classes.");
+
+ // If we have an empty base class, try to place it at offset 0.
+ if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
+ // We were able to place the class at offset 0.
+ // Since the base is empty we don't have to update the size or alignment.
+ UpdateEmptyClassOffsets(RD, 0);
+
+ return 0;
}
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
- uint64_t BaseSize = BaseInfo.getNonVirtualSize();
-
// Round up the current record size to the base's alignment boundary.
uint64_t Offset = llvm::RoundUpToAlignment(Size, BaseAlign);
// Reserve space for this base.
- Size = Offset + BaseSize;
+ Size = Offset + BaseInfo.getNonVirtualSize();
// Remember the next available offset.
NextOffset = Size;
diff --git a/test/SemaCXX/empty-class-layout.cpp b/test/SemaCXX/empty-class-layout.cpp
new file mode 100644
index 0000000000..24688fad07
--- /dev/null
+++ b/test/SemaCXX/empty-class-layout.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify
+
+#define SA(n, p) int a##n[(p) ? 1 : -1]
+
+struct A { int a; };
+SA(0, sizeof(A) == 4);
+
+struct B { };
+SA(1, sizeof(B) == 1);
+
+struct C : A, B { };
+SA(2, sizeof(C) == 4);