From 33500955d731c73717af52088b7fc0e7a85681e7 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 11 Jun 2010 00:33:02 +0000 Subject: [PATCH] Split DependentNameType into two types. DependentNameType represents the case of an elaborated-type-specifier like 'typename A::foo', and DependentTemplateSpecializationType represents the case of an elaborated-type-specifier like 'typename A::template B'. The TypeLoc representation of a DependentTST conveniently exactly matches that of an ElaboratedType wrapping a TST. Kill off the explicit rebuild methods for RebuildInCurrentInstantiation; the standard implementations work fine because the nested name specifier is computable in the newly-entered context. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105801 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 16 ++- include/clang/AST/RecursiveASTVisitor.h | 12 +-- include/clang/AST/TemplateBase.h | 26 +++++ include/clang/AST/Type.h | 115 ++++++++++++++++----- include/clang/AST/TypeLoc.h | 122 +++++++++++++++++++++-- include/clang/AST/TypeNodes.def | 1 + include/clang/Frontend/TypeXML.def | 5 + lib/AST/ASTContext.cpp | 75 +++++++++----- lib/AST/ASTImporter.cpp | 27 ++++- lib/AST/TemplateBase.cpp | 27 +++++ lib/AST/Type.cpp | 56 +++++++++-- lib/AST/TypePrinter.cpp | 32 ++++-- lib/CodeGen/Mangle.cpp | 32 +++--- lib/Frontend/PCHReader.cpp | 12 +++ lib/Frontend/PCHWriter.cpp | 10 ++ lib/Sema/SemaDecl.cpp | 10 +- lib/Sema/SemaTemplate.cpp | 106 ++++---------------- lib/Sema/SemaTemplateDeduction.cpp | 12 +++ lib/Sema/SemaType.cpp | 22 ++++ lib/Sema/TreeTransform.h | 127 ++++++++++++++++-------- 20 files changed, 607 insertions(+), 238 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 9746b0dfd3..359db6d826 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -98,6 +98,8 @@ class ASTContext { llvm::FoldingSet TemplateSpecializationTypes; llvm::FoldingSet ElaboratedTypes; llvm::FoldingSet DependentNameTypes; + llvm::FoldingSet + DependentTemplateSpecializationTypes; llvm::FoldingSet ObjCObjectTypes; llvm::FoldingSet ObjCObjectPointerTypes; @@ -621,10 +623,16 @@ public: NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType Canon = QualType()); - QualType getDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon = QualType()); + + QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + const TemplateArgumentListInfo &Args); + QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 81226e510e..af459ff680 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -586,14 +586,12 @@ DEF_TRAVERSE_TYPE(ElaboratedType, { }) DEF_TRAVERSE_TYPE(DependentNameType, { - if (T->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - } + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + }) - if (T->getTemplateId()) { - TRY_TO(VisitTemplateSpecializationType( - const_cast(T->getTemplateId()))); - } +DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); }) DEF_TRAVERSE_TYPE(ObjCInterfaceType, { }) diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 8b38001bd1..7d5123fb04 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -256,6 +256,10 @@ public: return Args.NumArgs; } + /// Determines whether two template arguments are superficially the + /// same. + bool structurallyEquals(const TemplateArgument &Other) const; + /// \brief Construct a template argument pack. void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); @@ -476,6 +480,28 @@ public: const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const TemplateArgument &Arg); + +inline TemplateSpecializationType::iterator + TemplateSpecializationType::end() const { + return getArgs() + getNumArgs(); +} + +inline DependentTemplateSpecializationType::iterator + DependentTemplateSpecializationType::end() const { + return getArgs() + getNumArgs(); +} + +inline const TemplateArgument & + TemplateSpecializationType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; +} + +inline const TemplateArgument & + DependentTemplateSpecializationType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; +} } // end namespace clang diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b5f0c47e7f..bae30ec718 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2426,7 +2426,7 @@ class TemplateSpecializationType // The bool is whether this is a current instantiation. llvm::PointerIntPair ContextAndCurrentInstantiation; - /// \brief The name of the template being specialized. + /// \brief The name of the template being specialized. TemplateName Template; /// \brief - The number of template arguments named in this class @@ -2476,7 +2476,7 @@ public: typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } - iterator end() const; + iterator end() const; // defined inline in TemplateBase.h /// \brief Retrieve the name of the template that we are specializing. TemplateName getTemplateName() const { return Template; } @@ -2491,7 +2491,7 @@ public: /// \brief Retrieve a specific template argument as a type. /// \precondition @c isArgType(Arg) - const TemplateArgument &getArg(unsigned Idx) const; + const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h bool isSugared() const { return !isDependentType() || isCurrentInstantiation(); @@ -2682,6 +2682,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: + ~ElaboratedType(); /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2726,11 +2727,8 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - typedef llvm::PointerUnion NameType; - /// \brief The type that this typename specifier refers to. - NameType Name; + const IdentifierInfo *Name; DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) @@ -2740,17 +2738,10 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { "DependentNameType requires a dependent nested-name-specifier"); } - DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const TemplateSpecializationType *Ty, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, true), - NNS(NNS), Name(Ty) { - assert(NNS->isDependent() && - "DependentNameType requires a dependent nested-name-specifier"); - } - friend class ASTContext; // ASTContext creates these public: + virtual ~DependentNameType(); /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2762,13 +2753,7 @@ public: /// form of the original typename was terminated by an identifier, /// e.g., "typename T::type". const IdentifierInfo *getIdentifier() const { - return Name.dyn_cast(); - } - - /// \brief Retrieve the type named by the typename specifier as a - /// type specialization. - const TemplateSpecializationType *getTemplateId() const { - return Name.dyn_cast(); + return Name; } bool isSugared() const { return false; } @@ -2779,10 +2764,10 @@ public: } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, NameType Name) { + NestedNameSpecifier *NNS, const IdentifierInfo *Name) { ID.AddInteger(Keyword); ID.AddPointer(NNS); - ID.AddPointer(Name.getOpaqueValue()); + ID.AddPointer(Name); } static bool classof(const Type *T) { @@ -2791,6 +2776,88 @@ public: static bool classof(const DependentNameType *T) { return true; } }; +/// DependentTemplateSpecializationType - Represents a template +/// specialization type whose template cannot be resolved, e.g. +/// A::template B +class DependentTemplateSpecializationType : + public TypeWithKeyword, public llvm::FoldingSetNode { + + /// The AST context. Unfortunately required in order to profile + /// template arguments. + ASTContext &Context; + + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + /// \brief The identifier of the template. + const IdentifierInfo *Name; + + /// \brief - The number of template arguments named in this class + /// template specialization. + unsigned NumArgs; + + const TemplateArgument *getArgBuffer() const { + return reinterpret_cast(this+1); + } + TemplateArgument *getArgBuffer() { + return reinterpret_cast(this+1); + } + + DependentTemplateSpecializationType(ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args, + QualType Canon); + + virtual void Destroy(ASTContext& C); + + friend class ASTContext; // ASTContext creates these + +public: + virtual ~DependentTemplateSpecializationType(); + + NestedNameSpecifier *getQualifier() const { return NNS; } + const IdentifierInfo *getIdentifier() const { return Name; } + + /// \brief Retrieve the template arguments. + const TemplateArgument *getArgs() const { + return getArgBuffer(); + } + + /// \brief Retrieve the number of template arguments. + unsigned getNumArgs() const { return NumArgs; } + + const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h + + typedef const TemplateArgument * iterator; + iterator begin() const { return getArgs(); } + iterator end() const; // inline in TemplateBase.h + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args); + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentTemplateSpecialization; + } + static bool classof(const DependentTemplateSpecializationType *T) { + return true; + } +}; + /// ObjCObjectType - Represents a class type in Objective C. /// Every Objective C type is a combination of a base type and a /// list of protocols. diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f988f0e33b..e043135f2f 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1033,13 +1033,20 @@ public: setLAngleLoc(Loc); setRAngleLoc(Loc); setTemplateNameLoc(Loc); + initializeArgLocs(getNumArgs(), getTypePtr()->getArgs(), + getArgInfos(), Loc); + } - for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { + static void initializeArgLocs(unsigned NumArgs, + const TemplateArgument *Args, + TemplateArgumentLocInfo *ArgInfos, + SourceLocation Loc) { + for (unsigned i = 0, e = NumArgs; i != e; ++i) { TemplateArgumentLocInfo Info; #ifndef NDEBUG // If asserts are enabled, be sure to initialize the argument // loc with the right kind of pointer. - switch (getTypePtr()->getArg(i).getKind()) { + switch (Args[i].getKind()) { case TemplateArgument::Expression: case TemplateArgument::Declaration: Info = TemplateArgumentLocInfo((Expr*) 0); @@ -1050,7 +1057,7 @@ public: break; case TemplateArgument::Template: - Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + Info = TemplateArgumentLocInfo(SourceRange(Loc), Loc); break; case TemplateArgument::Integral: @@ -1060,7 +1067,7 @@ public: break; } #endif - getArgInfos()[i] = Info; + ArgInfos[i] = Info; } } @@ -1251,9 +1258,9 @@ public: } }; -struct DependentNameLocInfo { - SourceLocation KeywordLoc; - SourceRange QualifierRange; +// This is exactly the structure of an ElaboratedTypeLoc whose inner +// type is some sort of TypeDeclTypeLoc. +struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; }; @@ -1303,6 +1310,107 @@ public: } }; +// This is exactly the structure of an ElaboratedTypeLoc whose inner +// type is some sort of TemplateSpecializationTypeLoc. +struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; + // followed by a TemplateArgumentLocInfo[] +}; + +class DependentTemplateSpecializationTypeLoc : + public ConcreteTypeLoc { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceLocation getLAngleLoc() const { + return this->getLocalData()->LAngleLoc; + } + void setLAngleLoc(SourceLocation Loc) { + this->getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return this->getLocalData()->RAngleLoc; + } + void setRAngleLoc(SourceLocation Loc) { + this->getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumArgs() const { + return getTypePtr()->getNumArgs(); + } + + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { +#ifndef NDEBUG + AI.validateForArgument(getTypePtr()->getArg(i)); +#endif + getArgInfos()[i] = AI; + } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { + return getArgInfos()[i]; + } + + TemplateArgumentLoc getArgLoc(unsigned i) const { + return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + return SourceRange(getKeywordLoc(), getRAngleLoc()); + else + return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + } + + void copy(DependentTemplateSpecializationTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + setNameLoc(Loc); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + TemplateSpecializationTypeLoc::initializeArgLocs(getNumArgs(), + getTypePtr()->getArgs(), + getArgInfos(), Loc); + } + + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(TemplateArgumentLocInfo); + } + +private: + TemplateArgumentLocInfo *getArgInfos() const { + return static_cast(getExtraLocalData()); + } +}; + } #endif diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 02508af67d..9cb56861a9 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -92,6 +92,7 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) +DEPENDENT_TYPE(DependentTemplateSpecialization, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index 069d718d9d..e8cb4a6de0 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -253,6 +253,11 @@ NODE_XML(DependentNameType, "DependentNameType") ID_ATTRIBUTE_XML END_NODE_XML +NODE_XML(DependentTemplateSpecializationType, + "DependentTemplateSpecializationType") + ID_ATTRIBUTE_XML +END_NODE_XML + NODE_XML(ObjCInterfaceType, "ObjCInterfaceType") ID_ATTRIBUTE_XML END_NODE_XML diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2e72449575..1cc8eb8fb2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1911,44 +1911,69 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, } QualType -ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon) { + const IdentifierInfo *Name, + const TemplateArgumentListInfo &Args) { + // TODO: avoid this copy + llvm::SmallVector ArgCopy; + for (unsigned I = 0, E = Args.size(); I != E; ++I) + ArgCopy.push_back(Args[I].getArgument()); + return getDependentTemplateSpecializationType(Keyword, NNS, Name, + ArgCopy.size(), + ArgCopy.data()); +} + +QualType +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; - DependentNameType::Profile(ID, Keyword, NNS, TemplateId); + DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, + Name, NumArgs, Args); void *InsertPos = 0; - DependentNameType *T - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentTemplateSpecializationType *T + = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); - if (Canon.isNull()) { - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - QualType CanonType = getCanonicalType(QualType(TemplateId, 0)); - ElaboratedTypeKeyword CanonKeyword = Keyword; - if (Keyword == ETK_None) - CanonKeyword = ETK_Typename; - if (CanonNNS != NNS || CanonKeyword != Keyword || - CanonType != QualType(TemplateId, 0)) { - const TemplateSpecializationType *CanonTemplateId - = CanonType->getAs(); - assert(CanonTemplateId && - "Canonical type must also be a template specialization type"); - Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId); - } + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + + ElaboratedTypeKeyword CanonKeyword = Keyword; + if (Keyword == ETK_None) CanonKeyword = ETK_Typename; + + bool AnyNonCanonArgs = false; + llvm::SmallVector CanonArgs(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) { + CanonArgs[I] = getCanonicalTemplateArgument(Args[I]); + if (!CanonArgs[I].structurallyEquals(Args[I])) + AnyNonCanonArgs = true; + } + + QualType Canon; + if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) { + Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS, + Name, NumArgs, + CanonArgs.data()); - DependentNameType *CheckT - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckT && "Typename canonical type is broken"); (void)CheckT; + // Find the insert position again. + DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); } - T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon); + void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs), + TypeAlignment); + T = new (Mem) DependentTemplateSpecializationType(*this, Keyword, NNS, + Name, NumArgs, Args, Canon); Types.push_back(T); - DependentNameTypes.InsertNode(T, InsertPos); + DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); return QualType(T, 0); } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 14fe980575..370dbc54a2 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -73,6 +73,7 @@ namespace { // FIXME: TemplateSpecializationType QualType VisitElaboratedType(ElaboratedType *T); // FIXME: DependentNameType + // FIXME: DependentTemplateSpecializationType QualType VisitObjCInterfaceType(ObjCInterfaceType *T); QualType VisitObjCObjectType(ObjCObjectType *T); QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); @@ -619,14 +620,32 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Typename1->getIdentifier(), Typename2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(Context, - QualType(Typename1->getTemplateId(), 0), - QualType(Typename2->getTemplateId(), 0))) - return false; break; } + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec1 = + cast(T1); + const DependentTemplateSpecializationType *Spec2 = + cast(T2); + if (!IsStructurallyEquivalent(Context, + Spec1->getQualifier(), + Spec2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Spec1->getIdentifier(), + Spec2->getIdentifier())) + return false; + if (Spec1->getNumArgs() != Spec2->getNumArgs()) + return false; + for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Spec1->getArg(I), Spec2->getArg(I))) + return false; + } + break; + } + case Type::ObjCInterface: { const ObjCInterfaceType *Iface1 = cast(T1); const ObjCInterfaceType *Iface2 = cast(T2); diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 1c775efe57..02e648879a 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -90,6 +90,33 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, } } +bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { + if (getKind() != Other.getKind()) return false; + + switch (getKind()) { + case Null: + case Type: + case Declaration: + case Template: + case Expression: + return TypeOrValue == Other.TypeOrValue; + + case Integral: + return getIntegralType() == Other.getIntegralType() && + *getAsIntegral() == *Other.getAsIntegral(); + + case Pack: + if (Args.NumArgs != Other.Args.NumArgs) return false; + for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) + if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) + return false; + return true; + } + + // Suppress warnings. + return false; +} + //===----------------------------------------------------------------------===// // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1aab65ebec..c8cdae3af8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -768,6 +768,7 @@ bool Type::isSpecifierType() const { case TemplateSpecialization: case Elaborated: case DependentName: + case DependentTemplateSpecialization: case ObjCInterface: case ObjCObject: case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers @@ -856,12 +857,56 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { } } +ElaboratedType::~ElaboratedType() {} +DependentNameType::~DependentNameType() {} +DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} + +void DependentTemplateSpecializationType::Destroy(ASTContext &C) { + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + // FIXME: Not all expressions get cloned, so we can't yet perform + // this destruction. + // if (Expr *E = getArg(Arg).getAsExpr()) + // E->Destroy(C); + } +} + +DependentTemplateSpecializationType::DependentTemplateSpecializationType( + ASTContext &Context, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, const IdentifierInfo *Name, + unsigned NumArgs, const TemplateArgument *Args, + QualType Canon) + : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true), + Context(Context), NNS(NNS), Name(Name), NumArgs(NumArgs) { + assert(NNS && NNS->isDependent() && + "DependentTemplateSpecializatonType requires dependent qualifier"); + for (unsigned I = 0; I != NumArgs; ++I) + new (&getArgBuffer()[I]) TemplateArgument(Args[I]); +} + +void +DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { + ID.AddInteger(Keyword); + ID.AddPointer(Qualifier); + ID.AddPointer(Name); + for (unsigned Idx = 0; Idx < NumArgs; ++Idx) + Args[Idx].Profile(ID, Context); +} + bool Type::isElaboratedTypeSpecifier() const { ElaboratedTypeKeyword Keyword; if (const ElaboratedType *Elab = dyn_cast(this)) Keyword = Elab->getKeyword(); else if (const DependentNameType *DepName = dyn_cast(this)) Keyword = DepName->getKeyword(); + else if (const DependentTemplateSpecializationType *DepTST = + dyn_cast(this)) + Keyword = DepTST->getKeyword(); else return false; @@ -1113,17 +1158,6 @@ void TemplateSpecializationType::Destroy(ASTContext& C) { } } -TemplateSpecializationType::iterator -TemplateSpecializationType::end() const { - return begin() + getNumArgs(); -} - -const TemplateArgument & -TemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateName T, diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index ccf6fb9362..2fa84f350b 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -580,15 +580,31 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) T->getQualifier()->print(OS, Policy); - if (const IdentifierInfo *Ident = T->getIdentifier()) - OS << Ident->getName(); - else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { - Spec->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Spec->getArgs(), - Spec->getNumArgs(), + OS << T->getIdentifier()->getName(); + } + + if (S.empty()) + S.swap(MyString); + else + S = MyString + ' ' + S; +} + +void TypePrinter::PrintDependentTemplateSpecialization( + const DependentTemplateSpecializationType *T, std::string &S) { + std::string MyString; + { + llvm::raw_string_ostream OS(MyString); + + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); + if (T->getKeyword() != ETK_None) + OS << " "; + + T->getQualifier()->print(OS, Policy); + OS << T->getIdentifier()->getName(); + OS << TemplateSpecializationType::PrintTemplateArgumentList( + T->getArgs(), + T->getNumArgs(), Policy); - } } if (S.empty()) diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index d8f1ca0b90..011e46941d 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1369,21 +1369,25 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { void CXXNameMangler::mangleType(const DependentNameType *T) { // Typename types are always nested Out << 'N'; - if (T->getIdentifier()) { - mangleUnresolvedScope(T->getQualifier()); - mangleSourceName(T->getIdentifier()); - } else { - const TemplateSpecializationType *TST = T->getTemplateId(); + mangleUnresolvedScope(T->getQualifier()); + mangleSourceName(T->getIdentifier()); + Out << 'E'; +} - mangleTemplatePrefix(TST->getTemplateName()); - - // FIXME: GCC does not appear to mangle the template arguments when - // the template in question is a dependent template name. Should we - // emulate that badness? - mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), - TST->getNumArgs()); - } - +void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) { + // Dependently-scoped template types are always nested + Out << 'N'; + + // TODO: avoid making this TemplateName. + TemplateName Prefix = + getASTContext().getDependentTemplateName(T->getQualifier(), + T->getIdentifier()); + mangleTemplatePrefix(Prefix); + + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(Prefix, T->getArgs(), T->getNumArgs()); Out << 'E'; } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index aebb7e1772..e555d9078f 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2367,6 +2367,18 @@ void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } +void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); + TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, + Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), + Record, Idx)); +} void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3d5b7d8156..a2f7482e20 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -408,6 +408,16 @@ void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { Writer.AddSourceRange(TL.getQualifierRange(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); } +void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + Writer.AddSourceLocation(TL.getKeywordLoc(), Record); + Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getLAngleLoc(), Record); + Writer.AddSourceLocation(TL.getRAngleLoc(), Record); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + Writer.AddTemplateArgumentLoc(TL.getArgLoc(I), Record); +} void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1a8f7aa481..6bad5da9c4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -87,8 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (!isClassName) return 0; - // We know from the grammar that this name refers to a type, so build a - // DependentNameType node to describe the type. + // We know from the grammar that this name refers to a type, + // so build a dependent node to describe the type. return CheckTypenameType(ETK_None, (NestedNameSpecifier *)SS->getScopeRep(), II, SourceLocation(), SS->getRange(), NameLoc @@ -196,12 +196,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else if (ObjCInterfaceDecl *IDecl = dyn_cast(IIDecl)) { T = Context.getObjCInterfaceType(IDecl); - } else if (UnresolvedUsingTypenameDecl *UUDecl = - dyn_cast(IIDecl)) { - // FIXME: preserve source structure information. - T = Context.getDependentNameType(ETK_None, - UUDecl->getTargetNestedNameSpecifier(), - &II); } else { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 2f18711e24..5208f28ca6 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5288,15 +5288,31 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } - T = Context.getDependentNameType(ETK_Typename, NNS, - cast(T)); + // TODO: it's really silly that we make a template specialization + // type earlier only to drop it again here. + TemplateSpecializationType *TST = cast(T); + DependentTemplateName *DTN = + TST->getTemplateName().getAsDependentTemplateName(); + assert(DTN && "dependent template has non-dependent name?"); + T = Context.getDependentTemplateSpecializationType(ETK_Typename, NNS, + DTN->getIdentifier(), + TST->getNumArgs(), + TST->getArgs()); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); + DependentTemplateSpecializationTypeLoc TL = + cast(TSI->getTypeLoc()); + if (InnerTSI) { + TemplateSpecializationTypeLoc TSTL = + cast(InnerTSI->getTypeLoc()); + TL.setLAngleLoc(TSTL.getLAngleLoc()); + TL.setRAngleLoc(TSTL.getRAngleLoc()); + for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); + } else { + TL.initializeLocal(SourceLocation()); + } TL.setKeywordLoc(TypenameLoc); TL.setQualifierRange(SS.getRange()); - - // FIXME: the inner type is a template here; remember its full source info - TL.setNameLoc(InnerTSI ? InnerTSI->getTypeLoc().getBeginLoc() : TemplateLoc); return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } @@ -5425,87 +5441,9 @@ namespace { Sema::OwningExprResult TransformExpr(Expr *E) { return getSema().Owned(E->Retain()); } - - /// \brief Transforms a typename type by determining whether the type now - /// refers to a member of the current instantiation, and then - /// type-checking and building an ElaboratedType (when possible). - QualType TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType); }; } -QualType -CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType) { - DependentNameType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS - = TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange(), - ObjectType); - if (!NNS) - return QualType(); - - // If the nested-name-specifier did not change, and we cannot compute the - // context corresponding to the nested-name-specifier, then this - // typename type will not change; exit early. - CXXScopeSpec SS; - SS.setRange(TL.getQualifierRange()); - SS.setScopeRep(NNS); - - QualType Result; - if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0) - Result = QualType(T, 0); - - // Rebuild the typename type, which will probably turn into a - // ElaboratedType. - else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - Result = QualType(T, 0); - else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), - NNS, NewTemplateId); - } else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - - if (Result.isNull()) - return QualType(); - - if (const ElaboratedType* ElabT = Result->getAs()) { - QualType NamedT = ElabT->getNamedType(); - if (isa(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } - ElaboratedTypeLoc NewTL = TLB.push(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { - DependentNameTypeLoc NewTL = TLB.push(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - NewTL.setNameLoc(TL.getNameLoc()); - } - return Result; -} - /// \brief Rebuilds a type within the context of the current instantiation. /// /// The type \p T is part of the type of an out-of-line member definition of diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 88ceeca58a..403d5543a6 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2624,6 +2624,18 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec + = cast(T); + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(), + OnlyDeduced, Depth, Used); + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); + break; + } + case Type::TypeOf: if (!OnlyDeduced) MarkUsedTemplateParameters(SemaRef, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index bec929dabf..48c17cde43 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1492,6 +1492,28 @@ namespace { // FIXME: load appropriate source location. TL.setNameLoc(DS.getTypeSpecTypeLoc()); } + void VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (Keyword == ETK_Typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo); + if (TInfo) { + TL.copy(cast( + TInfo->getTypeLoc())); + return; + } + } + TL.initializeLocal(SourceLocation()); + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); + // FIXME: load appropriate source location. + TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 26caaadd49..100ddcb141 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -533,16 +533,27 @@ public: /// By default, builds a new DependentNameType type from the /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. - QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType T) { - if (NNS->isDependent()) { - // If the name is still dependent, just build a new dependent name type. - CXXScopeSpec SS; - SS.setScopeRep(NNS); - if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(Keyword, NNS, - cast(T)); - } + QualType RebuildDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &Args) { + // Rebuild the template name. + // TODO: avoid TemplateName abstraction + TemplateName InstName = + getDerived().RebuildTemplateName(NNS, *Name, QualType()); + + // If it's still dependent, make a dependent specialization. + if (InstName.getAsDependentTemplateName()) + return SemaRef.Context.getDependentTemplateSpecializationType( + Keyword, NNS, Name, Args); + + // Otherwise, make an elaborated type wrapping a non-dependent + // specialization. + QualType T = + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + if (T.isNull()) return QualType(); return SemaRef.Context.getElaboratedType(Keyword, NNS, T); } @@ -3298,46 +3309,23 @@ QualType TreeTransform::TransformDependentNameType(TypeLocBuilder &TLB, if (!NNS) return QualType(); - QualType Result; - - if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = getDerived().TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (!getDerived().AlwaysRebuild() && - NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - return QualType(T, 0); - - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - NewTemplateId); - } else { - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - } + QualType Result + = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, + T->getIdentifier(), + TL.getKeywordLoc(), + TL.getQualifierRange(), + TL.getNameLoc()); if (Result.isNull()) return QualType(); if (const ElaboratedType* ElabT = Result->getAs()) { QualType NamedT = ElabT->getNamedType(); - if (isa(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } + TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); + ElaboratedTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { + } else { DependentNameTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); @@ -3346,6 +3334,61 @@ QualType TreeTransform::TransformDependentNameType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform:: + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + QualType ObjectType) { + DependentTemplateSpecializationType *T = TL.getTypePtr(); + + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(T->getQualifier(), + TL.getQualifierRange(), + ObjectType); + if (!NNS) + return QualType(); + + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(TL.getArgLoc(I), Loc)) + return QualType(); + NewTemplateArgs.addArgument(Loc); + } + + QualType Result = getDerived().RebuildDependentTemplateSpecializationType( + T->getKeyword(), + NNS, + T->getIdentifier(), + TL.getNameLoc(), + NewTemplateArgs); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType *ElabT = dyn_cast(Result)) { + QualType NamedT = ElabT->getNamedType(); + + // Copy information relevant to the template specialization. + TemplateSpecializationTypeLoc NamedTL + = TLB.push(NamedT); + NamedTL.setLAngleLoc(TL.getLAngleLoc()); + NamedTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); + + // Copy information relevant to the elaborated type. + ElaboratedTypeLoc NewTL = TLB.push(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierRange(TL.getQualifierRange()); + } else { + TLB.pushFullCopy(TL); + } + return Result; +} + template QualType TreeTransform::TransformObjCInterfaceType(TypeLocBuilder &TLB, -- 2.40.0