From: Douglas Gregor Date: Wed, 11 Nov 2009 16:58:32 +0000 (+0000) Subject: Instantiation of template template parameters for nested templates, e.g., X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9106ef78f8fcc9df1a60c7a5b64c7d967194207e;p=clang Instantiation of template template parameters for nested templates, e.g., template struct X { template class Y> struct Inner; }; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86844 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d37476259e..db797d6f98 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -64,6 +64,7 @@ namespace { Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); + Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); // Base case. FIXME: Remove once we can instantiate everything. @@ -973,6 +974,35 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( return Param; } +Decl * +TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( + TemplateTemplateParmDecl *D) { + // Instantiate the template parameter list of the template template parameter. + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams; + { + // Perform the actual substitution of template parameters within a new, + // local instantiation scope. + Sema::LocalInstantiationScope Scope(SemaRef); + InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + } + + // Build the template template parameter. + TemplateTemplateParmDecl *Param + = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - 1, D->getPosition(), + D->getIdentifier(), InstParams); + Param->setDefaultArgument(D->getDefaultArgument()); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); + + return Param; +} + Decl * TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { NestedNameSpecifier *NNS = diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index 4d948184ce..849d835541 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -108,3 +108,21 @@ struct X1 { template struct B { }; }; template struct X1::B; + +// Template template parameters +template +struct X2 { + template class> // expected-error{{cannot have type 'float'}} \ + // expected-note{{previous non-type template}} + struct Inner { }; +}; + +template // expected-note{{template non-type parameter}} + struct X2_arg; + +X2::Inner x2i1; +X2::Inner x2i2; // expected-note{{instantiation}} +X2::Inner x2i3; // expected-error{{template template argument has different}} + +