diff options
author | Anders Carlsson <andersca@mac.com> | 2010-05-08 23:06:26 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-05-08 23:06:26 +0000 |
commit | 836fc14e6cdad2362fc31f11bf7b14832cba34b9 (patch) | |
tree | 396d0103e95517d5f41651c696429b89dd360a28 /lib/AST/RecordLayoutBuilder.cpp | |
parent | 5764f613e61cb3183f3d7ceeafd23396de96ed16 (diff) |
Actually compute the empty subobject sizes. No functionality change yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103363 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 745e68f38f..2d4b769735 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -24,8 +24,8 @@ using namespace clang; ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context) : Context(Context), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false), - SizeOfLargestEmptySubobject(0), NonVirtualSize(0), NonVirtualAlignment(8), - FirstNearlyEmptyVBase(0) { } + NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0), + SizeOfLargestEmptySubobject(0) { } /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but /// no other data. @@ -39,6 +39,56 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const { return false; } +void +ASTRecordLayoutBuilder::ComputeEmptySubobjectSizes(const CXXRecordDecl *RD) { + // Check the bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t EmptySize = 0; + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + if (BaseDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } + + // Check the fields. + for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) { + const FieldDecl *FD = *I; + + const RecordType *RT = + Context.getBaseElementType(FD->getType())->getAs<RecordType>(); + + // We only care about record types. + if (!RT) + continue; + + uint64_t EmptySize = 0; + const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl); + if (MemberDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } +} + void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { const ASTRecordLayout::PrimaryBaseInfo &BaseInfo = Context.getASTRecordLayout(RD).getPrimaryBaseInfo(); @@ -522,8 +572,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { // If this is a C++ class, lay out the vtable and the non-virtual bases. const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); - if (RD) + if (RD) { + ComputeEmptySubobjectSizes(RD); LayoutNonVirtualBases(RD); + } LayoutFields(D); |