diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 48 | ||||
-rw-r--r-- | test/SemaTemplate/current-instantiation.cpp | 20 |
4 files changed, 81 insertions, 1 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index dabbcb4734..22d5db2944 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4134,7 +4134,9 @@ public: bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS); ExprResult RebuildExprInCurrentInstantiation(Expr *E); - + bool RebuildTemplateParamsInCurrentInstantiation( + TemplateParameterList *Params); + std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8e2ff5ca88..ecc81ccb83 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4789,6 +4789,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(NewFD->getLocation(), diag::err_destructor_template); return 0; } + + // If we're adding a template to a dependent context, we may need to + // rebuilding some of the types used within the template parameter list, + // now that we know what the current instantiation is. + if (DC->isDependentContext()) { + ContextRAII SavedContext(*this, DC); + if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, NewFD->getLocation(), diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index cf8848bc6e..929d74efa9 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -846,6 +846,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (RequireCompleteDeclContext(SS, SemanticContext)) return true; + // If we're adding a template to a dependent context, we may need to + // rebuilding some of the types used within the template parameter list, + // now that we know what the current instantiation is. + if (SemanticContext->isDependentContext()) { + ContextRAII SavedContext(*this, SemanticContext); + if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + LookupQualifiedName(Previous, SemanticContext); } else { SemanticContext = CurContext; @@ -6699,6 +6708,45 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { return false; } +/// \brief Rebuild the template parameters now that we know we're in a current +/// instantiation. +bool Sema::RebuildTemplateParamsInCurrentInstantiation( + TemplateParameterList *Params) { + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + Decl *Param = Params->getParam(I); + + // There is nothing to rebuild in a type parameter. + if (isa<TemplateTypeParmDecl>(Param)) + continue; + + // Rebuild the template parameter list of a template template parameter. + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Param)) { + if (RebuildTemplateParamsInCurrentInstantiation( + TTP->getTemplateParameters())) + return true; + + continue; + } + + // Rebuild the type of a non-type template parameter. + NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param); + TypeSourceInfo *NewTSI + = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(), + NTTP->getLocation(), + NTTP->getDeclName()); + if (!NewTSI) + return true; + + if (NewTSI != NTTP->getTypeSourceInfo()) { + NTTP->setTypeSourceInfo(NewTSI); + NTTP->setType(NewTSI->getType()); + } + } + + return false; +} + /// \brief Produces a formatted string that describes the binding of /// template parameters to template arguments. std::string diff --git a/test/SemaTemplate/current-instantiation.cpp b/test/SemaTemplate/current-instantiation.cpp index fe7213f143..ccef811e22 100644 --- a/test/SemaTemplate/current-instantiation.cpp +++ b/test/SemaTemplate/current-instantiation.cpp @@ -215,3 +215,23 @@ namespace PR9255 { }; }; } + +namespace rdar10194295 { + template<typename XT> + class X { + public: + enum Enum { Yes, No }; + template<Enum> void foo(); + template<Enum> class Inner; + }; + + template<typename XT> + template<typename X<XT>::Enum> + void X<XT>::foo() + { + } + + template<typename XT> + template<typename X<XT>::Enum> + class X<XT>::Inner { }; +} |