[cfe-commits] r82746 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp lib/AST/RecordLayoutBuilder.h lib/Frontend/ASTConsumers.cpp test/SemaCXX/empty-class-layout.cpp

Anders Carlsson andersca at mac.com
Thu Sep 24 18:54:38 PDT 2009


Author: andersca
Date: Thu Sep 24 20:54:38 2009
New Revision: 82746

URL: http://llvm.org/viewvc/llvm-project?rev=82746&view=rev
Log:
Who would have thought that empty classes were so tricky? Handle cases where an empty virtual base class needs to be moved aside because it conflicts with the first field.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h
    cfe/trunk/lib/Frontend/ASTConsumers.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=82746&r1=82745&r2=82746&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Thu Sep 24 20:54:38 2009
@@ -307,6 +307,39 @@
   // FIXME: Update fields and virtual bases.
 }
 
+void
+ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD, 
+                                                uint64_t Offset) {
+  QualType T = FD->getType();
+
+  if (const RecordType *RT = T->getAs<RecordType>()) {
+    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      UpdateEmptyClassOffsets(RD, Offset);
+      return;
+    }
+  }
+  
+  if (const ConstantArrayType *AT = Ctx.getAsConstantArrayType(T)) {
+    QualType ElemTy = Ctx.getBaseElementType(AT);
+    const RecordType *RT = ElemTy->getAs<RecordType>();
+    if (!RT)
+      return;
+    const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+    if (!RD)
+      return;
+    
+    const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
+
+    uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
+    unsigned ElementOffset = Offset;
+
+    for (uint64_t I = 0; I != NumElements; ++I) {
+      UpdateEmptyClassOffsets(RD, ElementOffset);
+      ElementOffset += Info.getSize();
+    }
+  }
+}
+
 uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
   const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
 
@@ -527,6 +560,8 @@
         // We can't try again.
         FieldOffset += FieldAlign;
       }
+      
+      UpdateEmptyClassOffsets(D, FieldOffset);
     }
   }
 

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=82746&r1=82745&r2=82746&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Thu Sep 24 20:54:38 2009
@@ -112,6 +112,10 @@
   /// EmptyClassOffsets map if the class is empty or has any empty bases or
   /// fields.
   void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset);
+
+  /// UpdateEmptyClassOffsets - Called after a field has been placed at the 
+  /// given offset.
+  void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
   
   /// FinishLayout - Finalize record layout. Adjust record size based on the
   /// alignment.

Modified: cfe/trunk/lib/Frontend/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTConsumers.cpp?rev=82746&r1=82745&r2=82746&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/ASTConsumers.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTConsumers.cpp Thu Sep 24 20:54:38 2009
@@ -540,6 +540,9 @@
       if (RD->isImplicit())
         continue;
 
+      if (RD->isDependentType())
+        continue;
+      
       // FIXME: Do we really need to hard code this?
       if (RD->getQualifiedNameAsString() == "__va_list_tag")
         continue;

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=82746&r1=82745&r2=82746&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/empty-class-layout.cpp (original)
+++ cfe/trunk/test/SemaCXX/empty-class-layout.cpp Thu Sep 24 20:54:38 2009
@@ -28,4 +28,18 @@
 struct J : Empty { 
   Empty e[2];
 };
-SA(5, sizeof(J) == 3);
\ No newline at end of file
+SA(5, sizeof(J) == 3);
+
+template<int N> struct Derived : Empty, Derived<N - 1> { 
+};
+template<> struct Derived<0> : Empty { };
+
+struct S1 : virtual Derived<10> { 
+  Empty e;
+};
+SA(6, sizeof(S1) == 24);
+
+struct S2 : virtual Derived<10> { 
+  Empty e[2];
+};
+SA(7, sizeof(S2) == 24);





More information about the cfe-commits mailing list