]> granicus.if.org Git - clang/commitdiff
A parameter pack must always come last in a class template.
authorAnders Carlsson <andersca@mac.com>
Fri, 12 Jun 2009 23:20:15 +0000 (23:20 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 12 Jun 2009 23:20:15 +0000 (23:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73269 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/variadic-class-template-1.cpp

index 865b1ce4f3c92408ef3c1cdb7ecb4bde47d0b5a1..5780959058a6e1bb5cbb11f2fdcc2e3ecd00d07c 100644 (file)
@@ -836,6 +836,8 @@ def err_template_kw_refers_to_function_template : Error<
 // C++0x Variadic Templates
 def err_template_param_pack_default_arg : Error<
   "template parameter pack cannot have a default argument">;
+def err_template_param_pack_must_be_last_template_parameter : Error<
+  "template parameter pack must be the last template parameter">;
 
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;
index e1b2084469b74491c4d488976b489e2437d24b6e..54c61f6cd9b4933b1966ca3d7e56d79179adf50b 100644 (file)
@@ -591,6 +591,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
   bool SawDefaultArgument = false;
   SourceLocation PreviousDefaultArgLoc;
 
+  bool SawParameterPack = false;
+  SourceLocation ParameterPackLoc;
+
   // Dummy initialization to avoid warnings.
   TemplateParameterList::iterator OldParam = NewParams->end();
   if (OldParams)
@@ -607,13 +610,27 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
     // Variables used to diagnose missing default arguments
     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) {
+      Diag(ParameterPackLoc, 
+           diag::err_template_param_pack_must_be_last_template_parameter);
+      Invalid = true;
+    }
+
     // Merge default arguments for template type parameters.
     if (TemplateTypeParmDecl *NewTypeParm
           = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
       TemplateTypeParmDecl *OldTypeParm 
           = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
       
-      if (OldTypeParm && OldTypeParm->hasDefaultArgument() && 
+      if (NewTypeParm->isParameterPack()) {
+        assert(!NewTypeParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+        ParameterPackLoc = NewTypeParm->getLocation();
+      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && 
           NewTypeParm->hasDefaultArgument()) {
         OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
         NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
index b811423e1f57786ae918a7603514c9526844d974..6df905006692a504866cc23e7e92a487676b5be2 100644 (file)
@@ -1,3 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
 
-template<typename... Args = int> struct S { }; // expected-error{{template parameter pack cannot have a default argument}}
+template<typename ... Args = int> struct S1 { }; // expected-error{{template parameter pack cannot have a default argument}}
+template<typename ... Args, typename T> struct S2 { }; // expected-error{{template parameter pack must be the last template parameter}}