aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-06-11 00:33:02 +0000
committerJohn McCall <rjmccall@apple.com>2010-06-11 00:33:02 +0000
commit33500955d731c73717af52088b7fc0e7a85681e7 (patch)
treed8f4b7ae0d9196e25aa00730f115b0daa888bd75
parent480076c3defdcaf07e8a87c81930da467a702425 (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.h16
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h12
-rw-r--r--include/clang/AST/TemplateBase.h26
-rw-r--r--include/clang/AST/Type.h115
-rw-r--r--include/clang/AST/TypeLoc.h122
-rw-r--r--include/clang/AST/TypeNodes.def1
-rw-r--r--include/clang/Frontend/TypeXML.def5
-rw-r--r--lib/AST/ASTContext.cpp75
-rw-r--r--lib/AST/ASTImporter.cpp27
-rw-r--r--lib/AST/TemplateBase.cpp27
-rw-r--r--lib/AST/Type.cpp56
-rw-r--r--lib/AST/TypePrinter.cpp32
-rw-r--r--lib/CodeGen/Mangle.cpp32
-rw-r--r--lib/Frontend/PCHReader.cpp12
-rw-r--r--lib/Frontend/PCHWriter.cpp10
-rw-r--r--lib/Sema/SemaDecl.cpp10
-rw-r--r--lib/Sema/SemaTemplate.cpp106
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp12
-rw-r--r--lib/Sema/SemaType.cpp22
-rw-r--r--lib/Sema/TreeTransform.h127
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())
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index d8f1ca0b90..011e46941d 100644
--- a/