diff options
-rw-r--r-- | include/clang/AST/Type.h | 23 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 127 | ||||
-rw-r--r-- | test/CodeGenCXX/visibility.cpp | 17 |
3 files changed, 117 insertions, 50 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 8ebd612cc8..f9fc90dc07 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1191,13 +1191,9 @@ private: /// (for C++0x variadic templates). unsigned ContainsUnexpandedParameterPack : 1; - /// \brief Nonzero if the cache (i.e. the bitfields here starting - /// with 'Cache') is valid. If so, then this is a - /// LangOptions::VisibilityMode+1. - mutable unsigned CacheValidAndVisibility : 2; - - /// \brief True if the visibility was set explicitly in the source code. - mutable unsigned CachedExplicitVisibility : 1; + /// \brief True if the cache (i.e. the bitfields here starting with + /// 'Cache') is valid. + mutable unsigned CacheValid : 1; /// \brief Linkage of this type. mutable unsigned CachedLinkage : 2; @@ -1209,15 +1205,7 @@ private: mutable unsigned FromAST : 1; bool isCacheValid() const { - return (CacheValidAndVisibility != 0); - } - Visibility getVisibility() const { - assert(isCacheValid() && "getting linkage from invalid cache"); - return static_cast<Visibility>(CacheValidAndVisibility-1); - } - bool isVisibilityExplicit() const { - assert(isCacheValid() && "getting linkage from invalid cache"); - return CachedExplicitVisibility; + return CacheValid; } Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); @@ -1373,8 +1361,7 @@ protected: TypeBits.InstantiationDependent = Dependent || InstantiationDependent; TypeBits.VariablyModified = VariablyModified; TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; - TypeBits.CacheValidAndVisibility = 0; - TypeBits.CachedExplicitVisibility = false; + TypeBits.CacheValid = false; TypeBits.CachedLocalOrUnnamed = false; TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index b802b55d78..e6687a7717 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2002,21 +2002,18 @@ namespace { /// \brief The cached properties of a type. class CachedProperties { - LinkageInfo LV; + Linkage L; bool local; public: - CachedProperties(LinkageInfo LV, bool local) : LV(LV), local(local) {} + CachedProperties(Linkage L, bool local) : L(L), local(local) {} - Linkage getLinkage() const { return LV.getLinkage(); } - Visibility getVisibility() const { return LV.getVisibility(); } - bool isVisibilityExplicit() const { return LV.isVisibilityExplicit(); } + Linkage getLinkage() const { return L; } bool hasLocalOrUnnamedType() const { return local; } friend CachedProperties merge(CachedProperties L, CachedProperties R) { - LinkageInfo MergedLV = L.LV; - MergedLV.merge(R.LV); - return CachedProperties(MergedLV, + Linkage MergedLinkage = minLinkage(L.L, R.L); + return CachedProperties(MergedLinkage, L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); } }; @@ -2036,10 +2033,8 @@ public: static CachedProperties get(const Type *T) { ensure(T); - LinkageInfo LV(T->TypeBits.getLinkage(), - T->TypeBits.getVisibility(), - T->TypeBits.isVisibilityExplicit()); - return CachedProperties(LV, T->TypeBits.hasLocalOrUnnamedType()); + return CachedProperties(T->TypeBits.getLinkage(), + T->TypeBits.hasLocalOrUnnamedType()); } static void ensure(const Type *T) { @@ -2051,10 +2046,7 @@ public: if (!T->isCanonicalUnqualified()) { const Type *CT = T->getCanonicalTypeInternal().getTypePtr(); ensure(CT); - T->TypeBits.CacheValidAndVisibility = - CT->TypeBits.CacheValidAndVisibility; - T->TypeBits.CachedExplicitVisibility = - CT->TypeBits.CachedExplicitVisibility; + T->TypeBits.CacheValid = true; T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage; T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed; return; @@ -2062,10 +2054,7 @@ public: // Compute the cached properties and then set the cache. CachedProperties Result = computeCachedProperties(T); - T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U; - T->TypeBits.CachedExplicitVisibility = Result.isVisibilityExplicit(); - assert(T->TypeBits.isCacheValid() && - T->TypeBits.getVisibility() == Result.getVisibility()); + T->TypeBits.CacheValid = true; T->TypeBits.CachedLinkage = Result.getLinkage(); T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); } @@ -2091,13 +2080,13 @@ static CachedProperties computeCachedProperties(const Type *T) { #include "clang/AST/TypeNodes.def" // Treat instantiation-dependent types as external. assert(T->isInstantiationDependentType()); - return CachedProperties(LinkageInfo(), false); + return CachedProperties(ExternalLinkage, false); 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(LinkageInfo(), false); + return CachedProperties(ExternalLinkage, false); case Type::Record: case Type::Enum: { @@ -2107,11 +2096,11 @@ static CachedProperties computeCachedProperties(const Type *T) { // - 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 - LinkageInfo LV = Tag->getLinkageAndVisibility(); + Linkage L = Tag->getLinkage(); bool IsLocalOrUnnamed = Tag->getDeclContext()->isFunctionOrMethod() || (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()); - return CachedProperties(LV, IsLocalOrUnnamed); + return CachedProperties(L, IsLocalOrUnnamed); } // C++ [basic.link]p8: @@ -2149,9 +2138,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return result; } case Type::ObjCInterface: { - LinkageInfo LV = - cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); - return CachedProperties(LV, false); + Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkage(); + return CachedProperties(L, false); } case Type::ObjCObject: return Cache::get(cast<ObjCObjectType>(T)->getBaseType()); @@ -2175,17 +2163,92 @@ bool Type::hasUnnamedOrLocalType() const { return TypeBits.hasLocalOrUnnamedType(); } +static LinkageInfo computeLinkageInfo(QualType T); + +static LinkageInfo computeLinkageInfo(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"); + +#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 instantiation-dependent types as external. + assert(T->isInstantiationDependentType()); + return LinkageInfo::external(); + + case Type::Builtin: + return LinkageInfo::external(); + + case Type::Record: + case Type::Enum: + return cast<TagType>(T)->getDecl()->getLinkageAndVisibility(); + + case Type::Complex: + return computeLinkageInfo(cast<ComplexType>(T)->getElementType()); + case Type::Pointer: + return computeLinkageInfo(cast<PointerType>(T)->getPointeeType()); + case Type::BlockPointer: + return computeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); + case Type::LValueReference: + case Type::RValueReference: + return computeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); + case Type::MemberPointer: { + const MemberPointerType *MPT = cast<MemberPointerType>(T); + LinkageInfo LV = computeLinkageInfo(MPT->getClass()); + LV.merge(computeLinkageInfo(MPT->getPointeeType())); + return LV; + } + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + return computeLinkageInfo(cast<ArrayType>(T)->getElementType()); + case Type::Vector: + case Type::ExtVector: + return computeLinkageInfo(cast<VectorType>(T)->getElementType()); + case Type::FunctionNoProto: + return computeLinkageInfo(cast<FunctionType>(T)->getResultType()); + case Type::FunctionProto: { + const FunctionProtoType *FPT = cast<FunctionProtoType>(T); + LinkageInfo LV = computeLinkageInfo(FPT->getResultType()); + for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(), + ae = FPT->arg_type_end(); ai != ae; ++ai) + LV.merge(computeLinkageInfo(*ai)); + return LV; + } + case Type::ObjCInterface: + return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); + case Type::ObjCObject: + return computeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); + case Type::ObjCObjectPointer: + return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); + case Type::Atomic: + return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); + } + + llvm_unreachable("unhandled type class"); +} + +static LinkageInfo computeLinkageInfo(QualType T) { + return computeLinkageInfo(T.getTypePtr()); +} + LinkageInfo Type::getLinkageAndVisibility() const { - Cache::ensure(this); - LinkageInfo LV(TypeBits.getLinkage(), TypeBits.getVisibility(), - TypeBits.isVisibilityExplicit()); + if (!isCanonicalUnqualified()) + return computeLinkageInfo(getCanonicalTypeInternal()); + + LinkageInfo LV = computeLinkageInfo(this); + assert(LV.getLinkage() == getLinkage()); return LV; } void Type::ClearLinkageCache() { - TypeBits.CacheValidAndVisibility = 0; + TypeBits.CacheValid = false; if (QualType(this, 0) != CanonicalType) - CanonicalType->TypeBits.CacheValidAndVisibility = 0; + CanonicalType->TypeBits.CacheValid = false; } Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const { diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index 537e89dc1b..87add446ba 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -1260,3 +1260,20 @@ namespace test66 { // CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv // CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv } + +namespace test67 { + template <typename T> + struct DEFAULT bar { + static void zed() {} + }; + + class foo; + class compute { + void f(foo *rootfoo); + }; + class DEFAULT foo; + + template struct bar<foo>; + // CHECK: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv + // CHECK-HIDDEN: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv +} |