]> granicus.if.org Git - clang/commitdiff
Implement C++0x [temp.param]p11 for non-type and template template
authorDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 16:19:19 +0000 (16:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 16:19:19 +0000 (16:19 +0000)
parameter packs. Also, the "no template parameters after a template
parameter pack" rule only applies to primary class templates.

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

lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.param/p11-0x.cpp [new file with mode: 0644]

index 8e7e1eef4afc38757a4422253422e041eaaa0b5d..4ac8a6c21c3d3a4f702a38eb9c1dcdf1ff3e90d9 100644 (file)
@@ -1144,9 +1144,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
     bool MissingDefaultArg = false;
 
     // C++0x [temp.param]p11:
-    // If a template parameter of a class template is a template parameter pack,
-    // it must be the last template parameter.
-    if (SawParameterPack) {
+    //   If a template parameter of a primary class template is a template 
+    //   parameter pack, it shall be the last template parameter.
+    if (SawParameterPack && TPC == TPC_ClassTemplate) {
       Diag(ParameterPackLoc,
            diag::err_template_param_pack_must_be_last_template_parameter);
       Invalid = true;
@@ -1211,7 +1211,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
       // Merge default arguments for non-type template parameters
       NonTypeTemplateParmDecl *OldNonTypeParm
         = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
-      if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
+      if (NewNonTypeParm->isParameterPack()) {
+        assert(!NewNonTypeParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+        ParameterPackLoc = NewNonTypeParm->getLocation();
+      } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
           NewNonTypeParm->hasDefaultArgument()) {
         OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
         NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
@@ -1254,7 +1259,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
       // Merge default arguments for template template parameters
       TemplateTemplateParmDecl *OldTemplateParm
         = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
-      if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
+      if (NewTemplateParm->isParameterPack()) {
+        assert(!NewTemplateParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+        ParameterPackLoc = NewTemplateParm->getLocation();
+      } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
           NewTemplateParm->hasDefaultArgument()) {
         OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
         NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
diff --git a/test/CXX/temp/temp.param/p11-0x.cpp b/test/CXX/temp/temp.param/p11-0x.cpp
new file mode 100644 (file)
index 0000000..00f56ab
--- /dev/null
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// If a template-parameter of a class template has a default
+// template-argument, each subsequent template-parameter shall either
+// have a default template-argument supplied or be a template
+// parameter pack.
+template<typename> struct vector;
+
+template<typename T = int, typename ...Types> struct X2t;
+template<int V = 0, int ...Values> struct X2nt;
+template<template<class> class M = vector, template<class> class... Metas>
+  struct X2tt;
+
+// If a template-parameter of a primary class template is a template
+// parameter pack, it shall be the last template-parameter .
+template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+struct X0t;
+
+template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+struct X0nt;
+
+template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+struct X0tt;
+
+// [ Note: These are not requirements for function templates or class
+// template partial specializations because template arguments can be
+// deduced (14.8.2). -- end note]
+template<typename... Types> struct X1t;
+template<typename ...Types, typename T> struct X1t<T, Types...> { };
+
+template<int... Values> struct X1nt;
+template<int ...Values, int V> struct X1nt<V, Values...> { };
+
+// FIXME: Need template template argument packs!
+// template<template<int> class... Meta> struct X1tt;
+// template<template<int> class... Meta, template<int> class M> 
+//  struct X1tt<M, Meta...> { };
+
+template<typename ...Types, typename T>
+void f1t(X1t<T, Types...>);
+
+template<int ...Values, int V>
+void f1nt(X1nt<V, Values...>);
+
+// FIXME: Need template template argument packs!
+// template<template<int> class... Meta, template<int> class M> 
+// void f1tt(X1tt<M, Meta...>);