Fix two issues with the substitution of template template parameters
when instantiating the declaration of a member template:
- Only check if the have a template template argument at a specific position
when we already know that we have template arguments at that level;
otherwise, we're substituting for a level-reduced template template
parameter.
- When trying to find an instantiated declaration for a template
template parameter, look into the instantiated scope. This was a
typo, where we had two checks for TemplateTypeParmDecl, one of
which should have been a TemplateTemplateParmDecl.
With these changes, tramp3d-v4 passes -fsyntax-only.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95421 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 5c5701a..ab66ef3 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -578,6 +578,14 @@
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return D;
+
TemplateName Template
= TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
@@ -585,14 +593,6 @@
return Template.getAsTemplateDecl();
}
- // If the corresponding template argument is NULL or non-existent, it's
- // because we are performing instantiation from explicitly-specified
- // template arguments in a function template, but there were some
- // arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
- TTP->getPosition()))
- return D;
-
// Fall through to find the instantiated declaration for this template
// template parameter.
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6597a85..e4017c5 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2159,7 +2159,7 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
DeclContext *ParentDC = D->getDeclContext();
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
- isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
ParentDC->isFunctionOrMethod()) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
diff --git a/test/SemaTemplate/member-function-template.cpp b/test/SemaTemplate/member-function-template.cpp
index 5ea8c10..aea6285 100644
--- a/test/SemaTemplate/member-function-template.cpp
+++ b/test/SemaTemplate/member-function-template.cpp
@@ -73,3 +73,15 @@
float &fr = x1->get<float>();
(void)x2->get<float>(); // expected-error{{implicit instantiation of undefined template}}
}
+
+// Instantiation of template template parameters in a member function
+// template.
+namespace TTP {
+ template<int Dim> struct X {
+ template<template<class> class M, class T> void f(const M<T>&);
+ };
+
+ template<typename T> struct Y { };
+
+ void test_f(X<3> x, Y<int> y) { x.f(y); }
+}