[cfe-commits] r122877 - in /cfe/trunk: lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.param/p11-0x.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 5 08:19:19 PST 2011


Author: dgregor
Date: Wed Jan  5 10:19:19 2011
New Revision: 122877

URL: http://llvm.org/viewvc/llvm-project?rev=122877&view=rev
Log:
Implement C++0x [temp.param]p11 for non-type and template template
parameter packs. Also, the "no template parameters after a template
parameter pack" rule only applies to primary class templates.

Added:
    cfe/trunk/test/CXX/temp/temp.param/p11-0x.cpp
Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122877&r1=122876&r2=122877&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jan  5 10:19:19 2011
@@ -1144,9 +1144,9 @@
     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 @@
       // 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 @@
       // 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();

Added: cfe/trunk/test/CXX/temp/temp.param/p11-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p11-0x.cpp?rev=122877&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.param/p11-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.param/p11-0x.cpp Wed Jan  5 10:19:19 2011
@@ -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...>);





More information about the cfe-commits mailing list