Add a new PrimaryBaseInfo struct that combines the record decl of a primary base with whether it's virtual or not.
llvm-svn: 90018
This commit is contained in:
parent
f942ee0297
commit
03ff379911
|
@ -47,6 +47,23 @@ class ASTRecordLayout {
|
|||
// FieldCount - Number of fields.
|
||||
unsigned FieldCount;
|
||||
|
||||
public:
|
||||
/// PrimaryBaseInfo - Contains info about a primary base.
|
||||
struct PrimaryBaseInfo {
|
||||
PrimaryBaseInfo() : Base(0), IsVirtual(false) {}
|
||||
|
||||
PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
|
||||
: Base(Base), IsVirtual(IsVirtual) {}
|
||||
|
||||
/// Base - The primary base.
|
||||
const CXXRecordDecl *Base;
|
||||
|
||||
/// IsVirtual - Whether the primary base is virtual or not.
|
||||
bool IsVirtual;
|
||||
};
|
||||
|
||||
private:
|
||||
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
|
||||
struct CXXRecordLayoutInfo {
|
||||
/// NonVirtualSize - The non-virtual size (in bits) of an object, which is
|
||||
/// the size of the object without virtual bases.
|
||||
|
@ -56,11 +73,9 @@ class ASTRecordLayout {
|
|||
/// which is the alignment of the object without virtual bases.
|
||||
uint64_t NonVirtualAlign;
|
||||
|
||||
/// PrimaryBase - The primary base for our vtable.
|
||||
const CXXRecordDecl *PrimaryBase;
|
||||
/// PrimaryBase - Wether or not the primary base was a virtual base.
|
||||
bool PrimaryBaseWasVirtual;
|
||||
|
||||
/// PrimaryBase - The primary base info for this record.
|
||||
PrimaryBaseInfo PrimaryBase;
|
||||
|
||||
/// BaseOffsets - Contains a map from base classes to their offset.
|
||||
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
|
||||
llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
|
||||
|
@ -92,7 +107,7 @@ class ASTRecordLayout {
|
|||
ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize,
|
||||
const uint64_t *fieldoffsets, unsigned fieldcount,
|
||||
uint64_t nonvirtualsize, unsigned nonvirtualalign,
|
||||
const CXXRecordDecl *PB, bool PBVirtual,
|
||||
const PrimaryBaseInfo &PrimaryBase,
|
||||
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
|
||||
unsigned numbases,
|
||||
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
|
||||
|
@ -105,8 +120,7 @@ class ASTRecordLayout {
|
|||
FieldOffsets[i] = fieldoffsets[i];
|
||||
}
|
||||
|
||||
CXXInfo->PrimaryBase = PB;
|
||||
CXXInfo->PrimaryBaseWasVirtual = PBVirtual;
|
||||
CXXInfo->PrimaryBase = PrimaryBase;
|
||||
CXXInfo->NonVirtualSize = nonvirtualsize;
|
||||
CXXInfo->NonVirtualAlign = nonvirtualalign;
|
||||
for (unsigned i = 0; i != numbases; ++i)
|
||||
|
@ -162,17 +176,21 @@ public:
|
|||
return CXXInfo->NonVirtualAlign;
|
||||
}
|
||||
|
||||
/// getPrimaryBase - Get the primary base.
|
||||
const CXXRecordDecl *getPrimaryBase() const {
|
||||
/// getPrimaryBaseInfo - Get the primary base info.
|
||||
const PrimaryBaseInfo &getPrimaryBaseInfo() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
return CXXInfo->PrimaryBase;
|
||||
}
|
||||
/// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual.
|
||||
bool getPrimaryBaseWasVirtual() const {
|
||||
assert(CXXInfo && "Record layout does not have C++ specific info!");
|
||||
|
||||
return CXXInfo->PrimaryBaseWasVirtual;
|
||||
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
|
||||
const CXXRecordDecl *getPrimaryBase() const {
|
||||
return getPrimaryBaseInfo().Base;
|
||||
}
|
||||
|
||||
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
|
||||
bool getPrimaryBaseWasVirtual() const {
|
||||
return getPrimaryBaseInfo().IsVirtual;
|
||||
}
|
||||
|
||||
/// getBaseClassOffset - Get the offset, in bits, for the given base class.
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#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/ADT/SmallSet.h>
|
||||
#include <llvm/Support/MathExtras.h>
|
||||
|
@ -24,7 +23,7 @@ using namespace clang;
|
|||
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
|
||||
: Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
|
||||
MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0),
|
||||
NonVirtualAlignment(8), PrimaryBase(0), PrimaryBaseWasVirtual(false) {}
|
||||
NonVirtualAlignment(8) { }
|
||||
|
||||
/// LayoutVtable - Lay out the vtable and set PrimaryBase.
|
||||
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
|
||||
|
@ -34,7 +33,7 @@ void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
|
|||
}
|
||||
|
||||
SelectPrimaryBase(RD);
|
||||
if (PrimaryBase == 0) {
|
||||
if (!PrimaryBase.Base) {
|
||||
int AS = 0;
|
||||
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
|
||||
Size += Ctx.Target.getPointerWidth(AS);
|
||||
|
@ -52,7 +51,7 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
|
|||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
// Skip the PrimaryBase here, as it is laid down first.
|
||||
if (Base != PrimaryBase || PrimaryBaseWasVirtual)
|
||||
if (Base != PrimaryBase.Base || PrimaryBase.IsVirtual)
|
||||
LayoutBaseNonVirtually(Base, false);
|
||||
}
|
||||
}
|
||||
|
@ -74,12 +73,13 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
|
|||
}
|
||||
|
||||
void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
|
||||
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
|
||||
const ASTRecordLayout::PrimaryBaseInfo &BaseInfo =
|
||||
Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo();
|
||||
|
||||
// If the record has a primary base class that is virtual, add it to the set
|
||||
// of primary bases.
|
||||
if (Layout.getPrimaryBaseWasVirtual())
|
||||
IndirectPrimaryBases.insert(Layout.getPrimaryBase());
|
||||
if (BaseInfo.IsVirtual)
|
||||
IndirectPrimaryBases.insert(BaseInfo.Base);
|
||||
|
||||
// Now traverse all bases and find primary bases for them.
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
|
@ -107,7 +107,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
|
|||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
if (!i->isVirtual()) {
|
||||
SelectPrimaryVBase(Base, FirstPrimary);
|
||||
if (PrimaryBase)
|
||||
if (PrimaryBase.Base)
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
|
|||
if (FirstPrimary==0)
|
||||
FirstPrimary = Base;
|
||||
if (!IndirectPrimaryBases.count(Base)) {
|
||||
setPrimaryBase(Base, true);
|
||||
setPrimaryBase(Base, /*IsVirtual=*/true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -141,14 +141,17 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
|
|||
// base class, if one exists.
|
||||
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()->getAs<RecordType>()->getDecl());
|
||||
if (Base->isDynamicClass()) {
|
||||
// We found it.
|
||||
setPrimaryBase(Base, false);
|
||||
return;
|
||||
}
|
||||
// Ignore virtual bases.
|
||||
if (i->isVirtual())
|
||||
continue;
|
||||
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
if (Base->isDynamicClass()) {
|
||||
// We found it.
|
||||
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,8 +169,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
|
|||
|
||||
// Otherwise if is the first nearly empty virtual base, if one exists,
|
||||
// otherwise there is no primary base class.
|
||||
if (!PrimaryBase)
|
||||
setPrimaryBase(FirstPrimary, true);
|
||||
if (!PrimaryBase.Base)
|
||||
setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
|
||||
}
|
||||
|
||||
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
|
||||
|
@ -232,9 +235,10 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
|
|||
}
|
||||
|
||||
if (Base->getNumVBases()) {
|
||||
const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
|
||||
const CXXRecordDecl *PB = L.getPrimaryBase();
|
||||
LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary);
|
||||
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
|
||||
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().Base;
|
||||
LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark,
|
||||
IndirectPrimary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -455,10 +459,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
|||
if (RD) {
|
||||
LayoutVtable(RD);
|
||||
// PrimaryBase goes first.
|
||||
if (PrimaryBase) {
|
||||
if (PrimaryBaseWasVirtual)
|
||||
IndirectPrimaryBases.insert(PrimaryBase);
|
||||
LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual);
|
||||
if (PrimaryBase.Base) {
|
||||
if (PrimaryBase.IsVirtual)
|
||||
IndirectPrimaryBases.insert(PrimaryBase.Base);
|
||||
LayoutBaseNonVirtually(PrimaryBase.Base, PrimaryBase.IsVirtual);
|
||||
}
|
||||
LayoutNonVirtualBases(RD);
|
||||
}
|
||||
|
@ -470,7 +474,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
|||
|
||||
if (RD) {
|
||||
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
|
||||
LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
|
||||
LayoutVirtualBases(RD, RD, PrimaryBase.Base, 0, mark, IndirectPrimaryBases);
|
||||
}
|
||||
|
||||
// Finally, round the size of the total struct up to the alignment of the
|
||||
|
@ -687,7 +691,6 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
|
|||
NonVirtualSize,
|
||||
Builder.NonVirtualAlignment,
|
||||
Builder.PrimaryBase,
|
||||
Builder.PrimaryBaseWasVirtual,
|
||||
Builder.Bases.data(),
|
||||
Builder.Bases.size(),
|
||||
Builder.VBases.data(),
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
|
||||
#define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
|
||||
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
@ -54,8 +55,8 @@ class ASTRecordLayoutBuilder {
|
|||
|
||||
uint64_t NonVirtualSize;
|
||||
unsigned NonVirtualAlignment;
|
||||
const CXXRecordDecl *PrimaryBase;
|
||||
bool PrimaryBaseWasVirtual;
|
||||
|
||||
ASTRecordLayout::PrimaryBaseInfo PrimaryBase;
|
||||
|
||||
typedef llvm::SmallVector<std::pair<const CXXRecordDecl *,
|
||||
uint64_t>, 4> BaseOffsetsTy;
|
||||
|
@ -94,9 +95,8 @@ class ASTRecordLayoutBuilder {
|
|||
/// base class.
|
||||
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
|
||||
|
||||
void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) {
|
||||
PrimaryBase = PB;
|
||||
PrimaryBaseWasVirtual = Virtual;
|
||||
void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) {
|
||||
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual);
|
||||
}
|
||||
|
||||
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
|
||||
|
|
Loading…
Reference in New Issue