//=== RecordLayoutBuilder.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 "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"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/MathExtras.h"
#include <map>
using namespace clang;
namespace {
/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
/// offsets while laying out a C++ class.
class EmptySubobjectMap {
ASTContext &Context;
/// Class - The class whose empty entries we're keeping track of.
const CXXRecordDecl *Class;
/// ComputeEmptySubobjectSizes - Compute the size of the largest base or
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
public:
/// This holds the size of the largest empty subobject (either a base
/// or a member). Will be zero if the record being built doesn't contain
/// any empty classes.
uint64_t SizeOfLargestEmptySubobject;
EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class)
: Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) { }
};
void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
// Check the bases.
for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
E = Class->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 = Class->field_begin(),
E = Class->field_end(); I !=