From 0004417e81d881bffd7190ae6fd2ce3553363b3b Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 29 Jul 2009 16:09:57 +0000 Subject: [PATCH] Use the new statement/expression profiling code to unique dependent template arguments, as in template specialization types. This permits matching out-of-line definitions of members for class templates that involve non-type template parameters. llvm-svn: 77462 --- clang/include/clang/AST/DeclTemplate.h | 23 ++++++++++--------- clang/include/clang/AST/Type.h | 13 +++++++---- clang/lib/AST/ASTContext.cpp | 7 +++--- clang/lib/AST/StmtProfile.cpp | 13 +++++++++++ clang/lib/AST/Type.cpp | 9 +++++--- clang/lib/Sema/SemaTemplate.cpp | 12 ++++++---- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++- .../temp.decls/temp.fct/temp.over.link/p6.cpp | 1 - .../test/SemaTemplate/injected-class-name.cpp | 10 +++++++- 9 files changed, 63 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 860162093131..17c8bc877d01 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -315,7 +315,7 @@ public: void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const { ID.AddInteger(Kind); switch (Kind) { case Null: @@ -326,7 +326,7 @@ public: break; case Declaration: - ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! + ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); break; case Integral: @@ -335,14 +335,13 @@ public: break; case Expression: - // FIXME: We need a canonical representation of expressions. - ID.AddPointer(getAsExpr()); + getAsExpr()->Profile(ID, Context, true); break; case Pack: ID.AddInteger(Args.NumArgs); for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I].Profile(ID); + Args.Args[I].Profile(ID, Context); } } }; @@ -534,15 +533,16 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, TemplateArguments->getFlatArgumentList(), - TemplateArguments->flat_size()); + TemplateArguments->flat_size(), + Function->getASTContext()); } static void Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + unsigned NumTemplateArgs, ASTContext &Context) { ID.AddInteger(NumTemplateArgs); for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) - TemplateArgs[Arg].Profile(ID); + TemplateArgs[Arg].Profile(ID, Context); } }; @@ -918,15 +918,16 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size()); + Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), + getASTContext()); } static void Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + unsigned NumTemplateArgs, ASTContext &Context) { ID.AddInteger(NumTemplateArgs); for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) - TemplateArgs[Arg].Profile(ID); + TemplateArgs[Arg].Profile(ID, Context); } static bool classof(const Decl *D) { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index be018026e36f..66d23f3eb561 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1782,14 +1782,18 @@ public: class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - /// \brief The name of the template being specialized. + // FIXME: Currently needed for profiling expressions; can we avoid this? + ASTContext &Context; + + /// \brief The name of the template being specialized. TemplateName Template; /// \brief - The number of template arguments named in this class /// template specialization. unsigned NumArgs; - TemplateSpecializationType(TemplateName T, + TemplateSpecializationType(ASTContext &Context, + TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon); @@ -1833,11 +1837,12 @@ public: const PrintingPolicy &Policy) const; void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Template, getArgs(), NumArgs); + Profile(ID, Template, getArgs(), NumArgs, Context); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, unsigned NumArgs); + const TemplateArgument *Args, unsigned NumArgs, + ASTContext &Context); static bool classof(const Type *T) { return T->getTypeClass() == TemplateSpecialization; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 931010d90465..f3a417181e7e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1682,7 +1682,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, // exists. llvm::FoldingSetNodeID ID; TemplateSpecializationType::Profile(ID, CanonTemplate, - CanonArgs.data(), NumArgs); + CanonArgs.data(), NumArgs, *this); void *InsertPos = 0; TemplateSpecializationType *Spec @@ -1693,7 +1693,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, void *Mem = Allocate((sizeof(TemplateSpecializationType) + sizeof(TemplateArgument) * NumArgs), 8); - Spec = new (Mem) TemplateSpecializationType(CanonTemplate, + Spec = new (Mem) TemplateSpecializationType(*this, CanonTemplate, CanonArgs.data(), NumArgs, QualType()); Types.push_back(Spec); @@ -1713,7 +1713,8 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, sizeof(TemplateArgument) * NumArgs), 8); TemplateSpecializationType *Spec - = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon); + = new (Mem) TemplateSpecializationType(*this, Template, Args, NumArgs, + Canon); Types.push_back(Spec); return QualType(Spec, 0); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 0f241c20ab2a..688777d4aacb 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -107,6 +107,10 @@ void StmtProfiler::VisitIfStmt(IfStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); } @@ -330,6 +334,10 @@ void StmtProfiler::VisitGNUNullExpr(GNUNullExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitVAArgExpr(VAArgExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitInitListExpr(InitListExpr *S) { if (S->getSyntacticForm()) { VisitInitListExpr(S->getSyntacticForm()); @@ -416,6 +424,10 @@ void StmtProfiler::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) { ID.AddBoolean(S->getValue()); } +void StmtProfiler::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) { VisitExpr(S); if (S->isTypeOperand()) @@ -595,6 +607,7 @@ void StmtProfiler::VisitDecl(Decl *D) { = dyn_cast_or_null(D)) { ID.AddInteger(NTTP->getDepth()); ID.AddInteger(NTTP->getIndex()); + VisitType(NTTP->getType()); return; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 04961ed0fcb8..f937d15ffb9f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1033,11 +1033,13 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { } TemplateSpecializationType:: -TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, +TemplateSpecializationType(ASTContext &Context, TemplateName T, + const TemplateArgument *Args, unsigned NumArgs, QualType Canon) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)), + Context(Context), Template(T), NumArgs(NumArgs) { assert((!Canon.isNull() || @@ -1074,10 +1076,11 @@ void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateName T, const TemplateArgument *Args, - unsigned NumArgs) { + unsigned NumArgs, + ASTContext &Context) { T.Profile(ID); for (unsigned Idx = 0; Idx < NumArgs; ++Idx) - Args[Idx].Profile(ID); + Args[Idx].Profile(ID, Context); } const Type *QualifierSet::strip(const Type* T) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 97812046f7f2..f27d551d1021 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -930,7 +930,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, llvm::FoldingSetNodeID ID; ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *Decl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -2433,12 +2434,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // FIXME: Template parameter list matters, too ClassTemplatePartialSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); } else ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = 0; @@ -2703,7 +2706,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, llvm::FoldingSetNodeID ID; ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index b04b63523df0..6506cde2af85 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -321,7 +321,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { llvm::FoldingSetNodeID ID; FunctionTemplateSpecializationInfo::Profile(ID, TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size()); + TemplateArgs.flat_size(), + SemaRef.Context); FunctionTemplateSpecializationInfo *Info = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp index 7606a2a6eef0..2571e45c5cde 100644 --- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s -// XFAIL template struct A0 { diff --git a/clang/test/SemaTemplate/injected-class-name.cpp b/clang/test/SemaTemplate/injected-class-name.cpp index c5f826d849ca..f9674c39a58b 100644 --- a/clang/test/SemaTemplate/injected-class-name.cpp +++ b/clang/test/SemaTemplate/injected-class-name.cpp @@ -19,7 +19,7 @@ X::X xi = x; // [temp.local]p1: -// FIXME: test non-type and template template parameters +// FIXME: test template template parameters template struct X0 { typedef T type; @@ -38,3 +38,11 @@ struct X0 { void f2(X0&); void f2(const ::X0&); // expected-error{{redecl}} }; + +template +struct X1 { + void f0(const X1&); // expected-note{{here}} + void f0(X1&); + void f0(const X1&); // expected-error{{redecl}} +}; +