[cfe-commits] r105628 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp test/SemaCXX/empty-class-layout.cpp

Anders Carlsson andersca at mac.com
Tue Jun 8 12:09:24 PDT 2010


Author: andersca
Date: Tue Jun  8 14:09:24 2010
New Revision: 105628

URL: http://llvm.org/viewvc/llvm-project?rev=105628&view=rev
Log:
Correctly handle fields with virtual bases containing empty subobjects.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/test/SemaCXX/empty-class-layout.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=105628&r1=105627&r2=105628&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Tue Jun  8 14:09:24 2010
@@ -201,7 +201,7 @@
   ClassVectorTy& Classes = EmptyClassOffsets[Offset];
   assert(std::find(Classes.begin(), Classes.end(), RD) == Classes.end() &&
          "Duplicate empty class detected!");
-    
+
   Classes.push_back(RD);
   
   // Update the empty class offset.
@@ -332,6 +332,19 @@
       return false;
   }
 
+  if (RD == Class) {
+    // This is the most derived class, traverse virtual bases as well.
+    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+         E = RD->vbases_end(); I != E; ++I) {
+      const CXXRecordDecl *VBaseDecl =
+        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+      
+      uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+      if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
+        return false;
+    }
+  }
+    
   // Traverse all member variables.
   unsigned FieldNo = 0;
   for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
@@ -402,6 +415,7 @@
 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, 
                                                    const CXXRecordDecl *Class,
                                                    uint64_t Offset) {
+  
   AddSubobjectAtOffset(RD, Offset);
 
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -419,6 +433,18 @@
     UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
   }
 
+  if (RD == Class) {
+    // This is the most derived class, traverse virtual bases as well.
+    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+         E = RD->vbases_end(); I != E; ++I) {
+      const CXXRecordDecl *VBaseDecl =
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+      
+      uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+      UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
+    }
+  }
+  
   // Traverse all member variables.
   unsigned FieldNo = 0;
   for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();

Modified: cfe/trunk/test/SemaCXX/empty-class-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/empty-class-layout.cpp?rev=105628&r1=105627&r2=105628&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/empty-class-layout.cpp (original)
+++ cfe/trunk/test/SemaCXX/empty-class-layout.cpp Tue Jun  8 14:09:24 2010
@@ -117,4 +117,30 @@
 struct C : B, Empty { };
 SA(0, sizeof(C) == 2);
 
-}
\ No newline at end of file
+}
+
+namespace Test5 {
+
+// Test that B::Empty isn't laid out at offset 0.
+struct Empty { };
+struct Field : virtual Empty { };
+struct A {
+  Field f;
+};
+struct B : A, Empty { };
+SA(0, sizeof(B) == 16);
+
+}
+
+namespace Test6 {
+
+// Test that B::A isn't laid out at offset 0.
+struct Empty { };
+struct Field : virtual Empty { };
+struct A {
+  Field f;
+};
+struct B : Empty, A { };
+SA(0, sizeof(B) == 16);
+
+}





More information about the cfe-commits mailing list