]> granicus.if.org Git - clang/commitdiff
More work on empty classes.
authorAnders Carlsson <andersca@mac.com>
Thu, 24 Sep 2009 03:22:10 +0000 (03:22 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 24 Sep 2009 03:22:10 +0000 (03:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82679 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
test/SemaCXX/empty-class-layout.cpp [new file with mode: 0644]

index 78598b795626f395cc76f237b6d8122054689ab3..062ce4f5bc2fd09dc8c77b2a6211aab80aa7bb44 100644 (file)
@@ -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 (file)
index 0000000..24688fa
--- /dev/null
@@ -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);