]> granicus.if.org Git - clang/commitdiff
Instantiation of template template parameters for nested templates, e.g.,
authorDouglas Gregor <dgregor@apple.com>
Wed, 11 Nov 2009 16:58:32 +0000 (16:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 11 Nov 2009 16:58:32 +0000 (16:58 +0000)
  template<typename T>
  struct X {
    template<template<T Value> class Y> struct Inner;
  };

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

lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/nested-template.cpp

index d37476259e0298d26134a181cf408e2548bfe826..db797d6f986bfee72b1154fb27b01cdb17e6eede 100644 (file)
@@ -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 =
index 4d948184cee9da2ed332a41624aa580243bc26fc..849d835541fed1f6dcb77cf8353a805d554ce1ef 100644 (file)
@@ -108,3 +108,21 @@ struct X1 {
   template<typename, bool = false> struct B { };
 };
 template struct X1<int>::B<bool>;
+
+// Template template parameters
+template<typename T>
+struct X2 {
+  template<template<class U, T Value> class>  // expected-error{{cannot have type 'float'}} \
+                                              // expected-note{{previous non-type template}}
+    struct Inner { };
+};
+
+template<typename T, 
+         int Value> // expected-note{{template non-type parameter}}
+  struct X2_arg;
+
+X2<int>::Inner<X2_arg> x2i1;
+X2<float>::Inner<X2_arg> x2i2; // expected-note{{instantiation}}
+X2<long>::Inner<X2_arg> x2i3; // expected-error{{template template argument has different}}
+
+