diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-07-19 00:18:47 +0000 | 
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-07-19 00:18:47 +0000 | 
| commit | 6d9f6f326dd5e7e886951e624d177a7d49d9f7e8 (patch) | |
| tree | 4f2f213da6ed0ebd6d5e36d602f9e74148a4cb70 /clang/lib/AST/RecordLayoutBuilder.cpp | |
| parent | 50bf9a60e5dee870c574d5c515034803c5a155f7 (diff) | |
| download | bcm5719-llvm-6d9f6f326dd5e7e886951e624d177a7d49d9f7e8.tar.gz bcm5719-llvm-6d9f6f326dd5e7e886951e624d177a7d49d9f7e8.zip  | |
Handle layout of non-virtual base classes.
llvm-svn: 76348
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
| -rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 64 | 
1 files changed, 60 insertions, 4 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 41272fdbfea..1dcc4f84650 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -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 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {    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 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,    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());  }  | 

