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

Anders Carlsson andersca at mac.com
Sat Jul 18 17:18:48 PDT 2009


Author: andersca
Date: Sat Jul 18 19:18:47 2009
New Revision: 76348

URL: http://llvm.org/viewvc/llvm-project?rev=76348&view=rev
Log:
Handle layout of non-virtual base classes.

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

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

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Jul 18 19:18:47 2009
@@ -11,6 +11,7 @@
 
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
@@ -20,9 +21,48 @@
 using namespace clang;
 
 ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) 
-  : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0), 
+  : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
   IsUnion(false) {}
 
+void 
+ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
+  assert(!RD->isPolymorphic() && 
+         "FIXME: We don't support polymorphic classes yet!");
+  
+  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+       e = RD->bases_end(); i != e; ++i) {
+    if (!i->isVirtual()) {
+      const CXXRecordDecl *Base = 
+        cast<CXXRecordDecl>(i->getType()->getAsRecordType()->getDecl());
+      LayoutNonVirtualBase(Base);
+    }
+  }
+}
+
+void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
+  const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
+    assert(BaseInfo.getDataSize() > 0 && 
+           "FIXME: Handle empty classes.");
+  
+  // FIXME: Should get the non-virtual alignment of the base.
+  unsigned BaseAlign = BaseInfo.getAlignment();
+  
+  // FIXME: Should get the non-virtual size of the base.
+  uint64_t BaseSize = BaseInfo.getDataSize();
+  
+  // Round up the current record size to the base's alignment boundary.
+  Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
+
+  // Reserve space for this base.
+  Size += BaseSize;
+  
+  // Remember the next available offset.
+  NextOffset = Size;
+  
+  // Remember max struct/class alignment.
+  UpdateAlignment(BaseAlign);
+}
+
 void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
   IsUnion = D->isUnion();
   
@@ -31,7 +71,11 @@
   
   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
     UpdateAlignment(AA->getAlignment());
-  
+
+  // If this is a C++ class, lay out the nonvirtual bases.
+  if (Ctx.getLangOptions().CPlusPlus)
+    LayoutNonVirtualBases(cast<CXXRecordDecl>(D));
+
   LayoutFields(D);
   
   // Finally, round the size of the total struct up to the alignment of the
@@ -191,8 +235,20 @@
 
   Builder.Layout(D);
 
-  return new ASTRecordLayout(Builder.Size, Builder.Alignment,
-                             Builder.NextOffset,
+  bool IsPODForThePurposeOfLayout;
+  if (!Ctx.getLangOptions().CPlusPlus) {
+    // In C, all record types are POD.
+    IsPODForThePurposeOfLayout = true;
+  } else {
+    // FIXME: This is not always correct. See the part about bitfields at
+    // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
+    IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
+  }
+  
+  uint64_t DataSize = 
+    IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
+  
+  return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
                              Builder.FieldOffsets.data(), 
                              Builder.FieldOffsets.size());
 }

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

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Sat Jul 18 19:18:47 2009
@@ -15,6 +15,7 @@
 namespace clang {
   class ASTContext;
   class ASTRecordLayout;
+  class CXXRecordDecl;
   class FieldDecl;
   class ObjCImplementationDecl;
   class ObjCInterfaceDecl;
@@ -34,12 +35,16 @@
   ASTRecordLayoutBuilder(ASTContext &Ctx);
   
   void Layout(const RecordDecl *D);
+  void Layout(const CXXRecordDecl *D);
   void Layout(const ObjCInterfaceDecl *D,
               const ObjCImplementationDecl *Impl);
 
   void LayoutFields(const RecordDecl *D);
   void LayoutField(const FieldDecl *D);
 
+  void LayoutNonVirtualBases(const CXXRecordDecl *RD);
+  void LayoutNonVirtualBase(const CXXRecordDecl *RD);
+  
   /// FinishLayout - Finalize record layout. Adjust record size based on the
   /// alignment.
   void FinishLayout();

Added: cfe/trunk/test/SemaCXX/class-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class-layout.cpp?rev=76348&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/class-layout.cpp (added)
+++ cfe/trunk/test/SemaCXX/class-layout.cpp Sat Jul 18 19:18:47 2009
@@ -0,0 +1,31 @@
+// 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;
+  char b;
+};
+
+SA(0, sizeof(A) == 8);
+
+struct B : A {
+  char c;
+};
+
+SA(1, sizeof(B) == 12);
+
+struct C {
+// Make fields private so C won't be a POD type.
+private:
+  int a;
+  char b;
+};
+
+SA(2, sizeof(C) == 8);
+
+struct D : C {
+  char c;
+};
+
+SA(3, sizeof(D) == 8);





More information about the cfe-commits mailing list