//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "RecordLayoutBuilder.h"
#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/Basic/TargetInfo.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/MathExtras.h"
using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context)
: Context(Context), Size(0), Alignment(8), Packed(false),
UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false),
NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0),
SizeOfLargestEmptySubobject(0) { }
/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
/// no other data.
bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
// FIXME: Audit the corners
if (!RD->isDynamicClass())
return false;
const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0))
return true;
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();
// If the record has a primary base class that is virtual, add it to the set
// of primary bases.
if (BaseInfo.isVirtual())
IndirectPrimaryBases.insert(BaseInfo.getBase());
// Now traverse all bases and find primary bases for them.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
assert(!i->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()