aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-09-25 15:39:00 +0000
committerAnders Carlsson <andersca@mac.com>2009-09-25 15:39:00 +0000
commit1eca99b815e531eba63233c0558af0dc971387aa (patch)
tree051c573a350231a314cf4381414e85b574be461f
parentbdbeeb50c5d182c591bd8797dc0485921df19e9d (diff)
Even more work on empty classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82770 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp38
-rw-r--r--test/SemaCXX/empty-class-layout.cpp14
2 files changed, 45 insertions, 7 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 2cf5925d39..470907012b 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -247,7 +247,18 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
return false;
}
- // FIXME: fields.
+ // Check fields.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
+
+ if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset))
+ return false;
+ }
+
// FIXME: virtual bases.
return true;
}
@@ -304,7 +315,17 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset);
}
- // FIXME: Update fields and virtual bases.
+ // Update fields.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
+ UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
+ }
+
+ // FIXME: Update virtual bases.
}
void
@@ -348,7 +369,7 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
// We were able to place the class at offset 0.
UpdateEmptyClassOffsets(RD, 0);
- Size = std::max(Size, BaseInfo.getNonVirtualSize());
+ Size = std::max(Size, BaseInfo.getSize());
return 0;
}
@@ -366,11 +387,14 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
Offset += BaseAlign;
}
- // Remember the next available offset.
- NextOffset = Offset + BaseInfo.getNonVirtualSize();
+ if (!RD->isEmpty()) {
+ // Remember the next available offset.
+ NextOffset = Offset + BaseInfo.getNonVirtualSize();
+
+ Size = std::max(Size, NextOffset);
+ } else
+ Size = std::max(Size, Offset + BaseInfo.getSize());
- Size = std::max(Size, NextOffset);
-
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign);
diff --git a/test/SemaCXX/empty-class-layout.cpp b/test/SemaCXX/empty-class-layout.cpp
index 09e7e4e373..ce6506553d 100644
--- a/test/SemaCXX/empty-class-layout.cpp
+++ b/test/SemaCXX/empty-class-layout.cpp
@@ -43,3 +43,17 @@ struct S2 : virtual Derived<10> {
Empty e[2];
};
SA(7, sizeof(S2) == 24);
+
+struct S3 {
+ Empty e;
+};
+
+struct S4 : Empty, S3 {
+};
+SA(8, sizeof(S4) == 2);
+
+struct S5 : S3, Empty {};
+SA(9, sizeof(S5) == 2);
+
+struct S6 : S5 { };
+SA(10, sizeof(S6) == 2);