]> granicus.if.org Git - clang/commitdiff
Even more work on empty classes.
authorAnders Carlsson <andersca@mac.com>
Fri, 25 Sep 2009 15:39:00 +0000 (15:39 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 25 Sep 2009 15:39:00 +0000 (15:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82770 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
test/SemaCXX/empty-class-layout.cpp

index 2cf5925d39def2fe55b7a9aefe1b3bd6743cf827..470907012b2ae24d73e3d6a6284af75fadb0d078 100644 (file)
@@ -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);
 
index 09e7e4e37332e165fe3284b676881e8d26cd2d10..ce6506553d78b4b0ab353e03be03520a2cf49805 100644 (file)
@@ -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);