aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp39
-rw-r--r--test/SemaTemplate/nested-template.cpp7
2 files changed, 46 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 00f148df6e..c30f48e803 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -61,6 +61,7 @@ namespace {
ClassTemplatePartialSpecializationDecl *D);
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
// Base case. FIXME: Remove once we can instantiate everything.
@@ -824,6 +825,8 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
D->wasDeclaredWithTypename(),
D->isParameterPack());
+ // FIXME: Do we actually want to perform substitution here? I don't think
+ // we do.
if (D->hasDefaultArgument()) {
QualType DefaultPattern = D->getDefaultArgument();
QualType DefaultInst
@@ -839,6 +842,42 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
+ NonTypeTemplateParmDecl *D) {
+ // Substitute into the type of the non-type template parameter.
+ QualType T;
+ DeclaratorInfo *DI = D->getDeclaratorInfo();
+ if (DI) {
+ DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ if (DI) T = DI->getType();
+ } else {
+ T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ DI = 0;
+ }
+ if (T.isNull())
+ return 0;
+
+ // Check that this type is acceptable for a non-type template parameter.
+ bool Invalid = false;
+ T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation());
+ if (T.isNull()) {
+ T = SemaRef.Context.IntTy;
+ Invalid = true;
+ }
+
+ NonTypeTemplateParmDecl *Param
+ = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getDepth() - 1, D->getPosition(),
+ D->getIdentifier(), T, DI);
+ if (Invalid)
+ Param->setInvalidDecl();
+
+ Param->setDefaultArgument(D->getDefaultArgument());
+ return Param;
+}
+
Decl *
TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
NestedNameSpecifier *NNS =
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
index 5ee2c99540..4d948184ce 100644
--- a/test/SemaTemplate/nested-template.cpp
+++ b/test/SemaTemplate/nested-template.cpp
@@ -101,3 +101,10 @@ struct X0<T*> {
template<typename U>
void f(U u = T()) { }
};
+
+// PR5103
+template<typename>
+struct X1 {
+ template<typename, bool = false> struct B { };
+};
+template struct X1<int>::B<bool>;