diff options
author | John McCall <rjmccall@apple.com> | 2010-06-11 00:33:02 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-06-11 00:33:02 +0000 |
commit | 33500955d731c73717af52088b7fc0e7a85681e7 (patch) | |
tree | d8f4b7ae0d9196e25aa00730f115b0daa888bd75 | |
parent | 480076c3defdcaf07e8a87c81930da467a702425 (diff) |
Split DependentNameType into two types. DependentNameType represents the
case of an elaborated-type-specifier like 'typename A<T>::foo', and
DependentTemplateSpecializationType represents the case of an
elaborated-type-specifier like 'typename A<T>::template B<T>'. 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
-rw-r--r-- | include/clang/AST/ASTContext.h | 16 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 12 | ||||
-rw-r--r-- | include/clang/AST/TemplateBase.h | 26 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 115 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 122 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Frontend/TypeXML.def | 5 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 75 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 27 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 27 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 56 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 32 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 32 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 12 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 106 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 22 | ||||
-rw-r--r-- | 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<TemplateSpecializationType> TemplateSpecializationTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<DependentNameType> DependentNameTypes; + llvm::FoldingSet<DependentTemplateSpecializationType> + DependentTemplateSpecializationTypes; llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; llvm::FoldingSet<ObjCObjectPointerType> 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<TemplateSpecializationType *>(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<ASTContext*, 1, bool> 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<const IdentifierInfo *, - const TemplateSpecializationType *> 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<const IdentifierInfo *>(); - } - - /// \brief Retrieve the type named by the typename specifier as a - /// type specialization. - const TemplateSpecializationType *getTemplateId() const { - return Name.dyn_cast<const TemplateSpecializationType *>(); + 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<T>::template B<T> +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<const TemplateArgument*>(this+1); + } + TemplateArgument *getArgBuffer() { + return reinterpret_cast<TemplateArgument*>(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<UnqualTypeLoc, + DependentTemplateSpecializationTypeLoc, + DependentTemplateSpecializationType, + DependentTemplateSpecializationLocInfo> { +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<TemplateArgumentLocInfo*>(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<TemplateArgument, 16> 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<TemplateSpecializationType>(); - 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<TemplateArgument, 16> 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<DependentTemplateSpecializationType>(T1); + const DependentTemplateSpecializationType *Spec2 = + cast<DependentTemplateSpecializationType>(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<ObjCInterfaceType>(T1); const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(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<ElaboratedType>(this)) Keyword = Elab->getKeyword(); else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this)) Keyword = DepName->getKeyword(); + else if (const DependentTemplateSpecializationType *DepTST = + dyn_cast<DependentTemplateSpecializationType>(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()) |