diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 19 | ||||
-rw-r--r-- | test/SemaTemplate/variadic-class-template-1.cpp | 3 |
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}} |