From: Anders Carlsson Date: Fri, 12 Jun 2009 23:20:15 +0000 (+0000) Subject: A parameter pack must always come last in a class template. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49d2557addafd2f43b6d2ff54cf77b4f250d1544;p=clang A parameter pack must always come last in a class template. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73269 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(*NewParam)) { TemplateTypeParmDecl *OldTypeParm = OldParams? cast(*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 struct S { }; // expected-error{{template parameter pack cannot have a default argument}} +template struct S1 { }; // expected-error{{template parameter pack cannot have a default argument}} +template struct S2 { }; // expected-error{{template parameter pack must be the last template parameter}}