diff --git a/clang/include/clang/AST/RecordLayout.h b/clang/include/clang/AST/RecordLayout.h index 9b1c640a40b2..c34a27e18f52 100644 --- a/clang/include/clang/AST/RecordLayout.h +++ b/clang/include/clang/AST/RecordLayout.h @@ -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 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 *bases, unsigned numbases, const std::pair *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. diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 5bc27b9d06f5..af270577bc6c 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -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 #include @@ -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(i->getType()->getAs()->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(i->getType()->getAs()->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(i->getType()->getAs()->getDecl()); - if (Base->isDynamicClass()) { - // We found it. - setPrimaryBase(Base, false); - return; - } + // Ignore virtual bases. + if (i->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->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 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(), diff --git a/clang/lib/AST/RecordLayoutBuilder.h b/clang/lib/AST/RecordLayoutBuilder.h index fe02d882cec8..69e0498917c7 100644 --- a/clang/lib/AST/RecordLayoutBuilder.h +++ b/clang/lib/AST/RecordLayoutBuilder.h @@ -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, 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;