]> granicus.if.org Git - clang/commitdiff
When performing substitution of default template template parameters
authorDouglas Gregor <dgregor@apple.com>
Wed, 15 Jun 2011 14:20:42 +0000 (14:20 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 15 Jun 2011 14:20:42 +0000 (14:20 +0000)
before the template parameters have acquired a proper context (e.g.,
because the enclosing context has yet to be built), provide empty
parameter lists for all outer template parameter scopes to inhibit any
substitution for those template parameters. Fixes PR9643 /
<rdar://problem/9251019>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133055 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/default-arguments.cpp

index 5d4caacd8124b2dc02712b463ed67555eb5e5dc7..d458050585f1cf88b89289f70f04f6641756dcdf 100644 (file)
@@ -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;
index 3c1964175b10422ef45950941695d8936aff80be..69e592ee2535cd675610a26126556b9124124893 100644 (file)
@@ -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()) {
index 9ea0fc2e4d52ad9aeb6b2a6ee81df5752a2fb3b3..6391369aa5c470ece2245470d6f5dd69d609607f 100644 (file)
@@ -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);
+  }
+}