From: Douglas Gregor Date: Fri, 14 Oct 2011 15:31:12 +0000 (+0000) Subject: When declaring an out-of-line template, attempt to rebuild any types X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2060650f2743650a815ce3daa414352911d408fd;p=clang When declaring an out-of-line template, attempt to rebuild any types within the template parameter list that may have changed now that we know the current instantiation. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141954 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(Param)) + continue; + + // Rebuild the template parameter list of a template template parameter. + if (TemplateTemplateParmDecl *TTP + = dyn_cast(Param)) { + if (RebuildTemplateParamsInCurrentInstantiation( + TTP->getTemplateParameters())) + return true; + + continue; + } + + // Rebuild the type of a non-type template parameter. + NonTypeTemplateParmDecl *NTTP = cast(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 + class X { + public: + enum Enum { Yes, No }; + template void foo(); + template class Inner; + }; + + template + template::Enum> + void X::foo() + { + } + + template + template::Enum> + class X::Inner { }; +}