aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaTemplate.cpp19
-rw-r--r--test/SemaTemplate/variadic-class-template-1.cpp3
3 files changed, 22 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 865b1ce4f3..5780959058 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e1b2084469..54c61f6cd9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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();
diff --git a/test/SemaTemplate/variadic-class-template-1.cpp b/test/SemaTemplate/variadic-class-template-1.cpp
index b811423e1f..6df9050066 100644
--- a/test/SemaTemplate/variadic-class-template-1.cpp
+++ b/test/SemaTemplate/variadic-class-template-1.cpp
@@ -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}}