From: John McCall Date: Wed, 1 Dec 2010 08:12:46 +0000 (+0000) Subject: Eliminate vtables from the Type hierarchy. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b7b2688bab0eac053d3e2938b329c8e523fd252b;p=clang Eliminate vtables from the Type hierarchy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120562 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7586e2d7ec..64cc1b1a6d 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -789,6 +789,7 @@ private: /// Bitfields required by the Type class. class TypeBitfields { friend class Type; + template friend class TypePropertyCache; /// TypeClass bitfield - Enum that specifies what subclass this belongs to. unsigned TC : 8; @@ -954,36 +955,9 @@ private: TypeBits.FromAST = V; } - void ensureCachedProperties() const; + template friend class TypePropertyCache; protected: - /// \brief Compute the cached properties of this type. - class CachedProperties { - char linkage; - char visibility; - bool local; - - public: - CachedProperties(Linkage linkage, Visibility visibility, bool local) - : linkage(linkage), visibility(visibility), local(local) {} - - Linkage getLinkage() const { return (Linkage) linkage; } - Visibility getVisibility() const { return (Visibility) visibility; } - bool hasLocalOrUnnamedType() const { return local; } - - friend CachedProperties merge(CachedProperties L, CachedProperties R) { - return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()), - minVisibility(L.getVisibility(), R.getVisibility()), - L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); - } - }; - - virtual CachedProperties getCachedProperties() const; - static CachedProperties getCachedProperties(QualType T) { - return getCachedProperties(T.getTypePtr()); - } - static CachedProperties getCachedProperties(const Type *T); - // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified) @@ -996,7 +970,6 @@ protected: TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; } - virtual ~Type(); friend class ASTContext; void setDependent(bool D = true) { TypeBits.Dependent = D; } @@ -1336,9 +1309,6 @@ public: ObjCSel // This represents the ObjC 'SEL' type. }; -protected: - virtual CachedProperties getCachedProperties() const; - public: BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), @@ -1392,9 +1362,6 @@ class ComplexType : public Type, public llvm::FoldingSetNode { } friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: QualType getElementType() const { return ElementType; } @@ -1424,9 +1391,6 @@ class PointerType : public Type, public llvm::FoldingSetNode { } friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: QualType getPointeeType() const { return PointeeType; } @@ -1458,9 +1422,6 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { } friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: // Get the pointee type. Pointee is required to always be a function type. @@ -1496,8 +1457,6 @@ protected: ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); } - virtual CachedProperties getCachedProperties() const; - public: bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; } bool isInnerRef() const { return ReferenceTypeBits.InnerRef; } @@ -1579,9 +1538,6 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { } friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: QualType getPointeeType() const { return PointeeType; } @@ -1649,8 +1605,6 @@ protected: friend class ASTContext; // ASTContext creates these. - virtual CachedProperties getCachedProperties() const; - public: QualType getElementType() const { return ElementType; } ArraySizeModifier getSizeModifier() const { @@ -1954,8 +1908,6 @@ protected: } friend class ASTContext; // ASTContext creates these. - virtual CachedProperties getCachedProperties() const; - public: QualType getElementType() const { return ElementType; } @@ -2057,8 +2009,6 @@ public: /// class of FunctionNoProtoType and FunctionProtoType. /// class FunctionType : public Type { - virtual void ANCHOR(); // Key function for FunctionType. - // The type returned by the function. QualType ResultType; @@ -2183,9 +2133,6 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { Info) {} friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: // No additional state past what FunctionType provides. @@ -2239,9 +2186,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: unsigned getNumArgs() const { return NumArgs; } QualType getArgType(unsigned i) const { @@ -2482,8 +2426,6 @@ class TagType : public Type { protected: TagType(TypeClass TC, const TagDecl *D, QualType can); - virtual CachedProperties getCachedProperties() const; - public: TagDecl *getDecl() const; @@ -2857,8 +2799,6 @@ protected: } public: - virtual ~TypeWithKeyword(); // pin vtable to Type.cpp - ElaboratedTypeKeyword getKeyword() const { return static_cast(TypeWithKeywordBits.Keyword); } @@ -2983,8 +2923,6 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: - virtual ~DependentNameType(); - /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -3051,8 +2989,6 @@ class DependentTemplateSpecializationType : friend class ASTContext; // ASTContext creates these public: - virtual ~DependentTemplateSpecializationType(); - NestedNameSpecifier *getQualifier() const { return NNS; } const IdentifierInfo *getIdentifier() const { return Name; } @@ -3144,9 +3080,6 @@ protected: ObjCObjectTypeBits.NumProtocols = 0; } -protected: - CachedProperties getCachedProperties() const; // key function - public: /// getBaseType - Gets the base type of this object type. This is /// always (possibly sugar for) one of: @@ -3254,9 +3187,6 @@ class ObjCInterfaceType : public ObjCObjectType { Decl(const_cast(D)) {} friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: /// getDecl - Get the declaration of this interface. ObjCInterfaceDecl *getDecl() const { return Decl; } @@ -3306,9 +3236,6 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. -protected: - virtual CachedProperties getCachedProperties() const; - public: /// getPointeeType - Gets the type pointed to by this ObjC pointer. /// The result will always be an ObjCObjectType or sugar thereof. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 136480b1cc..cdcaa52717 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" @@ -35,8 +36,6 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) { return false; } -Type::~Type() { } - unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { @@ -827,9 +826,6 @@ bool Type::isSpecifierType() const { } } -TypeWithKeyword::~TypeWithKeyword() { -} - ElaboratedTypeKeyword TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) { switch (TypeSpec) { @@ -910,10 +906,6 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { return ""; } -ElaboratedType::~ElaboratedType() {} -DependentNameType::~DependentNameType() {} -DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} - DependentTemplateSpecializationType::DependentTemplateSpecializationType( ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -1006,8 +998,6 @@ const char *BuiltinType::getName(const LangOptions &LO) const { return 0; } -void FunctionType::ANCHOR() {} // Key function for FunctionType. - QualType QualType::getNonLValueExprType(ASTContext &Context) const { if (const ReferenceType *RefType = getTypePtr()->getAs()) return RefType->getPointeeType(); @@ -1318,154 +1308,194 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getBaseType(), qual_begin(), getNumProtocols()); } -void Type::ensureCachedProperties() const { - if (!TypeBits.isCacheValid()) { - CachedProperties Result = getCachedProperties(); - TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U; - assert(TypeBits.isCacheValid() && - TypeBits.getVisibility() == Result.getVisibility()); - TypeBits.CachedLinkage = Result.getLinkage(); - TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); - } -} +namespace { -/// \brief Determine the linkage of this type. -Linkage Type::getLinkage() const { - if (this != CanonicalType.getTypePtr()) - return CanonicalType->getLinkage(); - - ensureCachedProperties(); - return TypeBits.getLinkage(); +/// \brief The cached properties of a type. +class CachedProperties { + char linkage; + char visibility; + bool local; + +public: + CachedProperties(Linkage linkage, Visibility visibility, bool local) + : linkage(linkage), visibility(visibility), local(local) {} + + Linkage getLinkage() const { return (Linkage) linkage; } + Visibility getVisibility() const { return (Visibility) visibility; } + bool hasLocalOrUnnamedType() const { return local; } + + friend CachedProperties merge(CachedProperties L, CachedProperties R) { + return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()), + minVisibility(L.getVisibility(), R.getVisibility()), + L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); + } +}; } -/// \brief Determine the linkage of this type. -Visibility Type::getVisibility() const { - if (this != CanonicalType.getTypePtr()) - return CanonicalType->getVisibility(); - - ensureCachedProperties(); - return TypeBits.getVisibility(); -} +static CachedProperties computeCachedProperties(const Type *T); -bool Type::hasUnnamedOrLocalType() const { - if (this != CanonicalType.getTypePtr()) - return CanonicalType->hasUnnamedOrLocalType(); +namespace clang { +/// The type-property cache. This is templated so as to be +/// instantiated at an internal type to prevent unnecessary symbol +/// leakage. +template class TypePropertyCache { +public: + static CachedProperties get(QualType T) { + return get(T.getTypePtr()); + } - ensureCachedProperties(); - return TypeBits.hasLocalOrUnnamedType(); -} + static CachedProperties get(const Type *T) { + ensure(T); + return CachedProperties(T->TypeBits.getLinkage(), + T->TypeBits.getVisibility(), + T->TypeBits.hasLocalOrUnnamedType()); + } -std::pair Type::getLinkageAndVisibility() const { - if (this != CanonicalType.getTypePtr()) - return CanonicalType->getLinkageAndVisibility(); + static void ensure(const Type *T) { + // If the cache is valid, we're okay. + if (T->TypeBits.isCacheValid()) return; + + // If this type is non-canonical, ask its canonical type for the + // relevant information. + if (QualType(T, 0) != T->CanonicalType) { + const Type *CT = T->CanonicalType.getTypePtr(); + ensure(CT); + T->TypeBits.CacheValidAndVisibility = + CT->TypeBits.CacheValidAndVisibility; + T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage; + T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed; + return; + } - ensureCachedProperties(); - return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility()); + // Compute the cached properties and then set the cache. + CachedProperties Result = computeCachedProperties(T); + T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U; + assert(T->TypeBits.isCacheValid() && + T->TypeBits.getVisibility() == Result.getVisibility()); + T->TypeBits.CachedLinkage = Result.getLinkage(); + T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); + } +}; } +// Instantiate the friend template at a private class. In a +// reasonable implementation, these symbols will be internal. +// It is terrible that this is the best way to accomplish this. +namespace { class Private {}; } +typedef TypePropertyCache Cache; -Type::CachedProperties Type::getCachedProperties(const Type *T) { - T = T->CanonicalType.getTypePtr(); - T->ensureCachedProperties(); - return CachedProperties(T->TypeBits.getLinkage(), - T->TypeBits.getVisibility(), - T->TypeBits.hasLocalOrUnnamedType()); -} - -void Type::ClearLinkageCache() { - if (this != CanonicalType.getTypePtr()) - CanonicalType->ClearLinkageCache(); - else - TypeBits.CacheValidAndVisibility = 0; -} +static CachedProperties computeCachedProperties(const Type *T) { + switch (T->getTypeClass()) { +#define TYPE(Class,Base) +#define NON_CANONICAL_TYPE(Class,Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("didn't expect a non-canonical type here"); -Type::CachedProperties Type::getCachedProperties() const { - // Treat dependent types as external. - if (isDependentType()) +#define TYPE(Class,Base) +#define DEPENDENT_TYPE(Class,Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + // Treat dependent types as external. + assert(T->isDependentType()); return CachedProperties(ExternalLinkage, DefaultVisibility, false); - // C++ [basic.link]p8: - // Names not covered by these rules have no linkage. - return CachedProperties(NoLinkage, DefaultVisibility, false); -} - -Type::CachedProperties BuiltinType::getCachedProperties() const { - // C++ [basic.link]p8: - // A type is said to have linkage if and only if: - // - it is a fundamental type (3.9.1); or - return CachedProperties(ExternalLinkage, DefaultVisibility, false); -} - -Type::CachedProperties TagType::getCachedProperties() const { - // C++ [basic.link]p8: - // - it is a class or enumeration type that is named (or has a name for - // linkage purposes (7.1.3)) and the name has linkage; or - // - it is a specialization of a class template (14); or - - NamedDecl::LinkageInfo LV = getDecl()->getLinkageAndVisibility(); - bool IsLocalOrUnnamed = - getDecl()->getDeclContext()->isFunctionOrMethod() || - (!getDecl()->getIdentifier() && - !getDecl()->getTypedefForAnonDecl()); - return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed); -} - -// C++ [basic.link]p8: -// - it is a compound type (3.9.2) other than a class or enumeration, -// compounded exclusively from types that have linkage; or -Type::CachedProperties ComplexType::getCachedProperties() const { - return Type::getCachedProperties(ElementType); -} - -Type::CachedProperties PointerType::getCachedProperties() const { - return Type::getCachedProperties(PointeeType); -} - -Type::CachedProperties BlockPointerType::getCachedProperties() const { - return Type::getCachedProperties(PointeeType); -} + case Type::Builtin: + // C++ [basic.link]p8: + // A type is said to have linkage if and only if: + // - it is a fundamental type (3.9.1); or + return CachedProperties(ExternalLinkage, DefaultVisibility, false); -Type::CachedProperties ReferenceType::getCachedProperties() const { - return Type::getCachedProperties(PointeeType); -} + case Type::Record: + case Type::Enum: { + const TagDecl *Tag = cast(T)->getDecl(); + + // C++ [basic.link]p8: + // - it is a class or enumeration type that is named (or has a name + // for linkage purposes (7.1.3)) and the name has linkage; or + // - it is a specialization of a class template (14); or + NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility(); + bool IsLocalOrUnnamed = + Tag->getDeclContext()->isFunctionOrMethod() || + (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()); + return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed); + } -Type::CachedProperties MemberPointerType::getCachedProperties() const { - return merge(Type::getCachedProperties(Class), - Type::getCachedProperties(PointeeType)); -} + // C++ [basic.link]p8: + // - it is a compound type (3.9.2) other than a class or enumeration, + // compounded exclusively from types that have linkage; or + case Type::Complex: + return Cache::get(cast(T)->getElementType()); + case Type::Pointer: + return Cache::get(cast(T)->getPointeeType()); + case Type::BlockPointer: + return Cache::get(cast(T)->getPointeeType()); + case Type::LValueReference: + case Type::RValueReference: + return Cache::get(cast(T)->getPointeeType()); + case Type::MemberPointer: { + const MemberPointerType *MPT = cast(T); + return merge(Cache::get(MPT->getClass()), + Cache::get(MPT->getPointeeType())); + } + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + return Cache::get(cast(T)->getElementType()); + case Type::Vector: + case Type::ExtVector: + return Cache::get(cast(T)->getElementType()); + case Type::FunctionNoProto: + return Cache::get(cast(T)->getResultType()); + case Type::FunctionProto: { + const FunctionProtoType *FPT = cast(T); + CachedProperties result = Cache::get(FPT->getResultType()); + for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(), + ae = FPT->arg_type_end(); ai != ae; ++ai) + result = merge(result, Cache::get(*ai)); + return result; + } + case Type::ObjCInterface: { + NamedDecl::LinkageInfo LV = + cast(T)->getDecl()->getLinkageAndVisibility(); + return CachedProperties(LV.linkage(), LV.visibility(), false); + } + case Type::ObjCObject: + return Cache::get(cast(T)->getBaseType()); + case Type::ObjCObjectPointer: + return Cache::get(cast(T)->getPointeeType()); + } -Type::CachedProperties ArrayType::getCachedProperties() const { - return Type::getCachedProperties(ElementType); -} + llvm_unreachable("unhandled type class"); -Type::CachedProperties VectorType::getCachedProperties() const { - return Type::getCachedProperties(ElementType); + // C++ [basic.link]p8: + // Names not covered by these rules have no linkage. + return CachedProperties(NoLinkage, DefaultVisibility, false); } -Type::CachedProperties FunctionNoProtoType::getCachedProperties() const { - return Type::getCachedProperties(getResultType()); +/// \brief Determine the linkage of this type. +Linkage Type::getLinkage() const { + Cache::ensure(this); + return TypeBits.getLinkage(); } -Type::CachedProperties FunctionProtoType::getCachedProperties() const { - CachedProperties Cached = Type::getCachedProperties(getResultType()); - for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end(); - A != AEnd; ++A) { - Cached = merge(Cached, Type::getCachedProperties(*A)); - } - return Cached; +/// \brief Determine the linkage of this type. +Visibility Type::getVisibility() const { + Cache::ensure(this); + return TypeBits.getVisibility(); } -Type::CachedProperties ObjCInterfaceType::getCachedProperties() const { - NamedDecl::LinkageInfo LV = getDecl()->getLinkageAndVisibility(); - return CachedProperties(LV.linkage(), LV.visibility(), false); +bool Type::hasUnnamedOrLocalType() const { + Cache::ensure(this); + return TypeBits.hasLocalOrUnnamedType(); } -Type::CachedProperties ObjCObjectType::getCachedProperties() const { - if (const ObjCInterfaceType *T = getBaseType()->getAs()) - return Type::getCachedProperties(T); - return CachedProperties(ExternalLinkage, DefaultVisibility, false); +std::pair Type::getLinkageAndVisibility() const { + Cache::ensure(this); + return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility()); } -Type::CachedProperties ObjCObjectPointerType::getCachedProperties() const { - return Type::getCachedProperties(PointeeType); +void Type::ClearLinkageCache() { + TypeBits.CacheValidAndVisibility = 0; + if (QualType(this, 0) != CanonicalType) + CanonicalType->TypeBits.CacheValidAndVisibility = 0; }