diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0c4e9e1eb334..00cc9b53b6d0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1195,9 +1195,6 @@ 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) @@ -1212,18 +1209,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SourceLocation OldDefaultLoc; SourceLocation NewDefaultLoc; - // Variables used to diagnose missing default arguments + // Variable used to diagnose missing default arguments bool MissingDefaultArg = false; - // C++0x [temp.param]p11: - // If a template parameter of a primary class template or alias template - // is a template parameter pack, it shall be the last template parameter. - if (SawParameterPack && - (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { - Diag(ParameterPackLoc, - diag::err_template_param_pack_must_be_last_template_parameter); - Invalid = true; - } + // Variable used to diagnose non-final parameter packs + bool SawParameterPack = false; if (TemplateTypeParmDecl *NewTypeParm = dyn_cast(*NewParam)) { @@ -1243,7 +1233,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, 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(); @@ -1288,7 +1277,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, 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(); @@ -1313,7 +1301,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (SawDefaultArgument) MissingDefaultArg = true; } else { - // Check the presence of a default argument here. TemplateTemplateParmDecl *NewTemplateParm = cast(*NewParam); @@ -1323,6 +1310,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, continue; } + // Check the presence of a default argument here. if (NewTemplateParm->hasDefaultArgument() && DiagnoseDefaultTemplateArgument(*this, TPC, NewTemplateParm->getLocation(), @@ -1336,7 +1324,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, 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(); @@ -1363,6 +1350,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, MissingDefaultArg = true; } + // C++0x [temp.param]p11: + // If a template parameter of a primary class template or alias template + // is a template parameter pack, it shall be the last template parameter. + if (SawParameterPack && (NewParam + 1) != NewParamEnd && + (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { + Diag((*NewParam)->getLocation(), + diag::err_template_param_pack_must_be_last_template_parameter); + Invalid = true; + } + if (RedundantDefaultArg) { // C++ [temp.param]p12: // A template-parameter shall not be given default arguments @@ -3047,6 +3044,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // in arguments for non-template parameter packs. if ((*Param)->isTemplateParameterPack()) { + if (!HasParameterPack) + return true; if (ArgumentPack.empty()) Converted.push_back(TemplateArgument(0, 0)); else { diff --git a/clang/test/CXX/temp/temp.param/p11-0x.cpp b/clang/test/CXX/temp/temp.param/p11-0x.cpp index 1971aa10c2c7..d2276a3bced3 100644 --- a/clang/test/CXX/temp/temp.param/p11-0x.cpp +++ b/clang/test/CXX/temp/temp.param/p11-0x.cpp @@ -24,8 +24,9 @@ template class M = vector, template class... Metas> // If a template-parameter of a primary class template or alias template is a // template parameter pack, it shall be the last template-parameter. template + int After, int After2> struct X0t; +X0t pr9789(); template using A0t = int;