diff options
Diffstat (limited to 'lib/AST/Type.cpp')
-rw-r--r-- | lib/AST/Type.cpp | 304 |
1 files changed, 189 insertions, 115 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index d21781dc3899..38f2a16fa16f 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1,4 +1,4 @@ -//===--- Type.cpp - Type representation and manipulation ------------------===// +//===- Type.cpp - Type representation and manipulation --------------------===// // // The LLVM Compiler Infrastructure // @@ -12,20 +12,44 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Type.h" +#include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Visibility.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> + using namespace clang; bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { @@ -125,12 +149,10 @@ DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(DependentSizedArray, et, can, sm, tq, + : ArrayType(DependentSizedArray, et, can, sm, tq, (et->containsUnexpandedParameterPack() || (e && e->containsUnexpandedParameterPack()))), - Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) -{ -} + Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, @@ -152,13 +174,11 @@ DependentSizedExtVectorType::DependentSizedExtVectorType(const SourceLocation loc) : Type(DependentSizedExtVector, can, /*Dependent=*/true, /*InstantiationDependent=*/true, - ElementType->isVariablyModifiedType(), + ElementType->isVariablyModifiedType(), (ElementType->containsUnexpandedParameterPack() || (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))), Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), - loc(loc) -{ -} + loc(loc) {} void DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, @@ -168,18 +188,37 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } +DependentAddressSpaceType::DependentAddressSpaceType( + const ASTContext &Context, QualType PointeeType, QualType can, + Expr *AddrSpaceExpr, SourceLocation loc) + : Type(DependentAddressSpace, can, /*Dependent=*/true, + /*InstantiationDependent=*/true, + PointeeType->isVariablyModifiedType(), + (PointeeType->containsUnexpandedParameterPack() || + (AddrSpaceExpr && + AddrSpaceExpr->containsUnexpandedParameterPack()))), + Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType), + loc(loc) {} + +void DependentAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType PointeeType, + Expr *AddrSpaceExpr) { + ID.AddPointer(PointeeType.getAsOpaquePtr()); + AddrSpaceExpr->Profile(ID, Context, true); +} + VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) : VectorType(Vector, vecType, nElements, canonType, vecKind) {} VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) - : Type(tc, canonType, vecType->isDependentType(), - vecType->isInstantiationDependentType(), - vecType->isVariablyModifiedType(), - vecType->containsUnexpandedParameterPack()), - ElementType(vecType) -{ + : Type(tc, canonType, vecType->isDependentType(), + vecType->isInstantiationDependentType(), + vecType->isVariablyModifiedType(), + vecType->containsUnexpandedParameterPack()), + ElementType(vecType) { VectorTypeBits.VecKind = vecKind; VectorTypeBits.NumElements = nElements; } @@ -354,11 +393,13 @@ const Type *Type::getUnqualifiedDesugaredType() const { } } } + bool Type::isClassType() const { if (const RecordType *RT = getAs<RecordType>()) return RT->getDecl()->isClass(); return false; } + bool Type::isStructureType() const { if (const RecordType *RT = getAs<RecordType>()) return RT->getDecl()->isStruct(); @@ -381,6 +422,7 @@ bool Type::isStructureOrClassType() const { } return false; } + bool Type::isVoidPointerType() const { if (const PointerType *PT = getAs<PointerType>()) return PT->getPointeeType()->isVoidType(); @@ -534,12 +576,11 @@ bool Type::isObjCInertUnsafeUnretainedType() const { ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) - : Type(ObjCTypeParam, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) -{ + : Type(ObjCTypeParam, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + OTPDecl(const_cast<ObjCTypeParamDecl*>(D)) { initialize(protocols); } @@ -547,12 +588,11 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) - : Type(ObjCObject, Canonical, Base->isDependentType(), - Base->isInstantiationDependentType(), - Base->isVariablyModifiedType(), - Base->containsUnexpandedParameterPack()), - BaseType(Base) -{ + : Type(ObjCObject, Canonical, Base->isDependentType(), + Base->isInstantiationDependentType(), + Base->isVariablyModifiedType(), + Base->containsUnexpandedParameterPack()), + BaseType(Base) { ObjCObjectTypeBits.IsKindOf = isKindOf; ObjCObjectTypeBits.NumTypeArgs = typeArgs.size(); @@ -603,13 +643,13 @@ ArrayRef<QualType> ObjCObjectType::getTypeArgs() const { if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) { // Terminate when we reach an interface type. if (isa<ObjCInterfaceType>(objcObject)) - return { }; + return {}; return objcObject->getTypeArgs(); } // No type arguments. - return { }; + return {}; } bool ObjCObjectType::isKindOfType() const { @@ -645,7 +685,7 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals( return ctx.getObjCObjectType(ctx.getQualifiedType(baseType, splitBaseType.Quals), getTypeArgsAsWritten(), - /*protocols=*/{ }, + /*protocols=*/{}, /*isKindOf=*/false); } @@ -658,10 +698,10 @@ const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals( return ctx.getObjCObjectPointerType(obj)->castAs<ObjCObjectPointerType>(); } -namespace { - template<typename F> -QualType simpleTransform(ASTContext &ctx, QualType type, F &&f); +static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f); + +namespace { /// Visitor used by simpleTransform() to perform the transformation. template<typename F> @@ -675,7 +715,8 @@ struct SimpleTransformVisitor } public: - SimpleTransformVisitor(ASTContext &ctx, F &&f) : Ctx(ctx), TheFunc(std::move(f)) { } + SimpleTransformVisitor(ASTContext &ctx, F &&f) + : Ctx(ctx), TheFunc(std::move(f)) {} // None of the clients of this transformation can occur where // there are dependent types, so skip dependent types. @@ -1044,10 +1085,12 @@ public: #undef TRIVIAL_TYPE_CLASS }; +} // namespace + /// Perform a simple type transformation that does not change the /// semantics of the type. template<typename F> -QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { +static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { // Transform the type. If it changed, return the transformed result. QualType transformed = f(type); if (transformed.getAsOpaquePtr() != type.getAsOpaquePtr()) @@ -1067,8 +1110,6 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { return ctx.getQualifiedType(result, splitType.Quals); } -} // end anonymous namespace - /// Substitute the given type arguments for Objective-C type /// parameters within the given type, recursively. QualType QualType::substObjCTypeArgs( @@ -1233,7 +1274,7 @@ QualType QualType::substObjCTypeArgs( if (typeArgs.empty() && context != ObjCSubstitutionContext::Superclass) { return ctx.getObjCObjectType( - objcObjectType->getBaseType(), { }, + objcObjectType->getBaseType(), {}, protocols, objcObjectType->isKindOfTypeAsWritten()); } @@ -1343,7 +1384,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( objectType = objectPointerType->getObjectType(); } else if (getAs<BlockPointerType>()) { ASTContext &ctx = dc->getParentASTContext(); - objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { }) + objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, {}, {}) ->castAs<ObjCObjectType>(); } else { objectType = getAs<ObjCObjectType>(); @@ -1522,6 +1563,7 @@ const ObjCObjectType *Type::getAsObjCInterfaceType() const { } return nullptr; } + const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) { if (OPT->getInterfaceType()) @@ -1559,14 +1601,17 @@ TagDecl *Type::getAsTagDecl() const { } namespace { + class GetContainedDeducedTypeVisitor : public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> { bool Syntactic; + public: GetContainedDeducedTypeVisitor(bool Syntactic = false) : Syntactic(Syntactic) {} using TypeVisitor<GetContainedDeducedTypeVisitor, Type*>::Visit; + Type *Visit(QualType T) { if (T.isNull()) return nullptr; @@ -1579,50 +1624,64 @@ namespace { } // Only these types can contain the desired 'auto' type. + Type *VisitElaboratedType(const ElaboratedType *T) { return Visit(T->getNamedType()); } + Type *VisitPointerType(const PointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitBlockPointerType(const BlockPointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitReferenceType(const ReferenceType *T) { return Visit(T->getPointeeTypeAsWritten()); } + Type *VisitMemberPointerType(const MemberPointerType *T) { return Visit(T->getPointeeType()); } + Type *VisitArrayType(const ArrayType *T) { return Visit(T->getElementType()); } + Type *VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { return Visit(T->getElementType()); } + Type *VisitVectorType(const VectorType *T) { return Visit(T->getElementType()); } + Type *VisitFunctionProtoType(const FunctionProtoType *T) { if (Syntactic && T->hasTrailingReturn()) return const_cast<FunctionProtoType*>(T); return VisitFunctionType(T); } + Type *VisitFunctionType(const FunctionType *T) { return Visit(T->getReturnType()); } + Type *VisitParenType(const ParenType *T) { return Visit(T->getInnerType()); } + Type *VisitAttributedType(const AttributedType *T) { return Visit(T->getModifiedType()); } + Type *VisitAdjustedType(const AdjustedType *T) { return Visit(T->getOriginalType()); } }; -} + +} // namespace DeducedType *Type::getContainedDeducedType() const { return cast_or_null<DeducedType>( @@ -1673,7 +1732,6 @@ bool Type::isIntegralType(const ASTContext &Ctx) const { return false; } - bool Type::isIntegralOrUnscopedEnumerationType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && @@ -1689,8 +1747,6 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { return false; } - - bool Type::isCharType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Char_U || @@ -2015,7 +2071,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. if (isNull()) - return 0; + return false; if ((*this)->isIncompleteArrayType()) return Context.getBaseElementType(*this).isCXX98PODType(Context); @@ -2063,7 +2119,7 @@ bool QualType::isTrivialType(const ASTContext &Context) const { // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. if (isNull()) - return 0; + return false; if ((*this)->isArrayType()) return Context.getBaseElementType(*this).isTrivialType(Context); @@ -2563,6 +2619,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "double"; case LongDouble: return "long double"; + case Float16: + return "_Float16"; case Float128: return "__float128"; case WChar_S: @@ -2835,7 +2893,6 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumParams, const ExtProtoInfo &epi, const ASTContext &Context, bool Canonical) { - // We have to be careful not to get ambiguous profile encodings. // Note that valid type pointers are never ambiguous with anything else. // @@ -2897,12 +2954,11 @@ QualType TypedefType::desugar() const { } TypeOfExprType::TypeOfExprType(Expr *E, QualType can) - : Type(TypeOfExpr, can, E->isTypeDependent(), - E->isInstantiationDependent(), - E->getType()->isVariablyModifiedType(), - E->containsUnexpandedParameterPack()), - TOExpr(E) { -} + : Type(TypeOfExpr, can, E->isTypeDependent(), + E->isInstantiationDependent(), + E->getType()->isVariablyModifiedType(), + E->containsUnexpandedParameterPack()), + TOExpr(E) {} bool TypeOfExprType::isSugared() const { return !TOExpr->isTypeDependent(); @@ -2924,13 +2980,11 @@ DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can) // C++11 [temp.type]p2: "If an expression e involves a template parameter, // decltype(e) denotes a unique dependent type." Hence a decltype type is // type-dependent even if its expression is only instantiation-dependent. - : Type(Decltype, can, E->isInstantiationDependent(), - E->isInstantiationDependent(), - E->getType()->isVariablyModifiedType(), - E->containsUnexpandedParameterPack()), - E(E), - UnderlyingType(underlyingType) { -} + : Type(Decltype, can, E->isInstantiationDependent(), + E->isInstantiationDependent(), + E->getType()->isVariablyModifiedType(), + E->containsUnexpandedParameterPack()), + E(E), UnderlyingType(underlyingType) {} bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); } @@ -2942,7 +2996,7 @@ QualType DecltypeType::desugar() const { } DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E) - : DecltypeType(E, Context.DependentTy), Context(Context) { } + : DecltypeType(E, Context.DependentTy), Context(Context) {} void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E) { @@ -2953,26 +3007,23 @@ UnaryTransformType::UnaryTransformType(QualType BaseType, QualType UnderlyingType, UTTKind UKind, QualType CanonicalType) - : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(), - BaseType->isInstantiationDependentType(), - BaseType->isVariablyModifiedType(), - BaseType->containsUnexpandedParameterPack()) - , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) -{} + : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(), + BaseType->isInstantiationDependentType(), + BaseType->isVariablyModifiedType(), + BaseType->containsUnexpandedParameterPack()), + BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) {} DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C, QualType BaseType, UTTKind UKind) - : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) -{} - + : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) {} TagType::TagType(TypeClass TC, const TagDecl *D, QualType can) - : Type(TC, can, D->isDependentType(), - /*InstantiationDependent=*/D->isDependentType(), - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), - decl(const_cast<TagDecl*>(D)) {} + : Type(TC, can, D->isDependentType(), + /*InstantiationDependent=*/D->isDependentType(), + /*VariablyModified=*/false, + /*ContainsUnexpandedParameterPack=*/false), + decl(const_cast<TagDecl*>(D)) {} static TagDecl *getInterestingTagDecl(TagDecl *decl) { for (auto I : decl->redecls()) { @@ -2991,6 +3042,19 @@ bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); } +bool RecordType::hasConstFields() const { + for (FieldDecl *FD : getDecl()->fields()) { + QualType FieldTy = FD->getType(); + if (FieldTy.isConstQualified()) + return true; + FieldTy = FieldTy.getCanonicalType(); + if (const RecordType *FieldRecTy = FieldTy->getAs<RecordType>()) + if (FieldRecTy->hasConstFields()) + return true; + } + return false; +} + bool AttributedType::isQualifier() const { switch (getAttrKind()) { // These are type qualifiers in the traditional C sense: they annotate @@ -3104,11 +3168,9 @@ SubstTemplateTypeParmPackType:: SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack) - : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), - Replaced(Param), - Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) -{ -} + : Type(SubstTemplateTypeParmPack, Canon, true, true, false, true), + Replaced(Param), + Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {} TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); @@ -3275,11 +3337,13 @@ public: L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); } }; -} + +} // namespace static CachedProperties computeCachedProperties(const Type *T); namespace clang { + /// The type-property cache. This is templated so as to be /// instantiated at an internal type to prevent unnecessary symbol /// leakage. @@ -3317,13 +3381,19 @@ public: T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); } }; -} + +} // namespace clang // 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<Private> Cache; +namespace { + +class Private {}; + +} // namespace + +using Cache = TypePropertyCache<Private>; static CachedProperties computeCachedProperties(const Type *T) { switch (T->getTypeClass()) { @@ -3428,9 +3498,7 @@ bool Type::hasUnnamedOrLocalType() const { return TypeBits.hasLocalOrUnnamedType(); } -static LinkageInfo computeLinkageInfo(QualType T); - -static LinkageInfo computeLinkageInfo(const Type *T) { +LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { switch (T->getTypeClass()) { #define TYPE(Class,Base) #define NON_CANONICAL_TYPE(Class,Base) case Type::Class: @@ -3454,75 +3522,78 @@ static LinkageInfo computeLinkageInfo(const Type *T) { case Type::Record: case Type::Enum: - return cast<TagType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<TagType>(T)->getDecl()); case Type::Complex: - return computeLinkageInfo(cast<ComplexType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<ComplexType>(T)->getElementType()); case Type::Pointer: - return computeLinkageInfo(cast<PointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<PointerType>(T)->getPointeeType()); case Type::BlockPointer: - return computeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); case Type::LValueReference: case Type::RValueReference: - return computeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); + return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - LinkageInfo LV = computeLinkageInfo(MPT->getClass()); - LV.merge(computeLinkageInfo(MPT->getPointeeType())); + LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass()); + LV.merge(computeTypeLinkageInfo(MPT->getPointeeType())); return LV; } case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: - return computeLinkageInfo(cast<ArrayType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<ArrayType>(T)->getElementType()); case Type::Vector: case Type::ExtVector: - return computeLinkageInfo(cast<VectorType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<VectorType>(T)->getElementType()); case Type::FunctionNoProto: - return computeLinkageInfo(cast<FunctionType>(T)->getReturnType()); + return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType()); case Type::FunctionProto: { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); - LinkageInfo LV = computeLinkageInfo(FPT->getReturnType()); + LinkageInfo LV = computeTypeLinkageInfo(FPT->getReturnType()); for (const auto &ai : FPT->param_types()) - LV.merge(computeLinkageInfo(ai)); + LV.merge(computeTypeLinkageInfo(ai)); return LV; } case Type::ObjCInterface: - return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<ObjCInterfaceType>(T)->getDecl()); case Type::ObjCObject: - return computeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); + return computeTypeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); case Type::ObjCObjectPointer: - return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); + return computeTypeLinkageInfo( + cast<ObjCObjectPointerType>(T)->getPointeeType()); case Type::Atomic: - return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); + return computeTypeLinkageInfo(cast<AtomicType>(T)->getValueType()); case Type::Pipe: - return computeLinkageInfo(cast<PipeType>(T)->getElementType()); + return computeTypeLinkageInfo(cast<PipeType>(T)->getElementType()); } llvm_unreachable("unhandled type class"); } -static LinkageInfo computeLinkageInfo(QualType T) { - return computeLinkageInfo(T.getTypePtr()); -} - bool Type::isLinkageValid() const { if (!TypeBits.isCacheValid()) return true; - return computeLinkageInfo(getCanonicalTypeInternal()).getLinkage() == - TypeBits.getLinkage(); + Linkage L = LinkageComputer{} + .computeTypeLinkageInfo(getCanonicalTypeInternal()) + .getLinkage(); + return L == TypeBits.getLinkage(); } -LinkageInfo Type::getLinkageAndVisibility() const { - if (!isCanonicalUnqualified()) - return computeLinkageInfo(getCanonicalTypeInternal()); +LinkageInfo LinkageComputer::getTypeLinkageAndVisibility(const Type *T) { + if (!T->isCanonicalUnqualified()) + return computeTypeLinkageInfo(T->getCanonicalTypeInternal()); - LinkageInfo LV = computeLinkageInfo(this); - assert(LV.getLinkage() == getLinkage()); + LinkageInfo LV = computeTypeLinkageInfo(T); + assert(LV.getLinkage() == T->getLinkage()); return LV; } +LinkageInfo Type::getLinkageAndVisibility() const { + return LinkageComputer{}.getTypeLinkageAndVisibility(this); +} + Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const { QualType type(this, 0); do { @@ -3634,6 +3705,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: + case Type::DependentAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: @@ -3748,11 +3820,13 @@ bool Type::isObjCIndependentClassType() const { return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>(); return false; } + bool Type::isObjCRetainableType() const { return isObjCObjectPointerType() || isBlockPointerType() || isObjCNSObjectType(); } + bool Type::isObjCIndirectLifetimeType() const { if (isObjCLifetimeType()) return true; |