summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp10
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp16
-rw-r--r--clang/test/SemaTemplate/default-arguments.cpp15
3 files changed, 29 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5d4caacd812..d458050585f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2912,16 +2912,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// arguments, just break out now and we'll fill in the argument pack below.
if ((*Param)->isTemplateParameterPack())
break;
-
- // If our template is a template template parameter that hasn't acquired
- // its proper context yet (e.g., because we're using the template template
- // parameter in the signature of a function template, before we've built
- // the function template itself), don't attempt substitution of default
- // template arguments at this point: we don't have enough context to
- // do it properly.
- if (isTemplateTemplateParameter &&
- Template->getDeclContext()->isTranslationUnit())
- break;
// We have a default template argument that we will use.
TemplateArgumentLoc Arg;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 3c1964175b1..69e592ee253 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -62,8 +62,20 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (!Ctx) {
Ctx = D->getDeclContext();
- assert((!D->isTemplateParameter() || !Ctx->isTranslationUnit()) &&
- "Template parameter doesn't have its context yet!");
+ // If we have a template template parameter with translation unit context,
+ // then we're performing substitution into a default template argument of
+ // this template template parameter before we've constructed the template
+ // that will own this template template parameter. In this case, we
+ // use empty template parameter lists for all of the outer templates
+ // to avoid performing any substitutions.
+ if (Ctx->isTranslationUnit()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
+ Result.addOuterTemplateArguments(0, 0);
+ return Result;
+ }
+ }
}
while (!Ctx->isFileContext()) {
diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp
index 9ea0fc2e4d5..6391369aa5c 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -121,3 +121,18 @@ X6<long, X5b> x6c;
template<template<class> class X = B<int> > struct X7; // expected-error{{must be a class template}}
+
+namespace PR9643 {
+ template<typename T> class allocator {};
+ template<typename T, typename U = allocator<T> > class vector {};
+
+ template<template<typename U, typename = allocator<U> > class container,
+ typename DT>
+ container<DT> initializer(const DT& d) {
+ return container<DT>();
+ }
+
+ void f() {
+ vector<int, allocator<int> > v = initializer<vector>(5);
+ }
+}
OpenPOWER on IntegriCloud