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

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

index dec6402d3699953d2da4d7f7b0c20f5b5748941a..38c3e37352aa837e477a3347b79effff05a39526 100644 (file)
@@ -252,6 +252,18 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
   return true;
 }
 
+bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, 
+                                                   uint64_t Offset) const {
+  if (const RecordType *RT = dyn_cast<RecordType>(FD->getType())) {
+    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+      return canPlaceRecordAtOffset(RD, Offset);
+  }
+  
+  // FIXME: Arrays.
+  
+  return true;
+}
+
 void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
                                                      uint64_t Offset) {
   if (RD->isEmpty())
@@ -485,6 +497,17 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
 
     // Round up the current record size to the field's alignment boundary.
     FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
+    
+    if (!IsUnion) {
+      while (true) {
+        // Check if we can place the field at this offset.
+        if (canPlaceFieldAtOffset(D, FieldOffset))
+          break;
+        
+        // We can't try again.
+        FieldOffset += FieldAlign;
+      }
+    }
   }
 
   // Place this field at the current location.
index 43563c6729b9fac2c6df039a559e64d14db1c5e7..0f83661cd9a8862e1f0fcd5eb88dcb44efce843d 100644 (file)
@@ -103,6 +103,10 @@ class ASTRecordLayoutBuilder {
   /// (direct or indirect) of the same type having the same offset.
   bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset) const;
 
+  /// canPlaceFieldAtOffset - Return whether a field can be placed at the given
+  /// offset.
+  bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const;
+
   /// UpdateEmptyClassOffsets - Called after a record (either a base class
   /// or a field) has been placed at the given offset. Will update the
   /// EmptyClassOffsets map if the class is empty or has any empty bases or
index ebbeb38fc96fe5602b45703243bd49ad06d87f7a..625e3ee9036e952a9c9506c39b3a5191ac6b301f 100644 (file)
@@ -17,3 +17,10 @@ struct F : E { };
 
 struct G : E, F { };
 SA(3, sizeof(G) == 2);
+
+struct H { H(); };
+
+struct I : H { 
+  H h;
+};
+SA(4, sizeof(I) == 2);