diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8e7e1eef4afc..4ac8a6c21c3d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1144,9 +1144,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, 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) { + // If a template parameter of a primary class template is a template + // parameter pack, it shall be the last template parameter. + if (SawParameterPack && TPC == TPC_ClassTemplate) { Diag(ParameterPackLoc, diag::err_template_param_pack_must_be_last_template_parameter); Invalid = true; @@ -1211,7 +1211,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast(*OldParam) : 0; - if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && + if (NewNonTypeParm->isParameterPack()) { + 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(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); @@ -1254,7 +1259,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast(*OldParam) : 0; - if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && + if (NewTemplateParm->isParameterPack()) { + 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(); NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); diff --git a/clang/test/CXX/temp/temp.param/p11-0x.cpp b/clang/test/CXX/temp/temp.param/p11-0x.cpp new file mode 100644 index 000000000000..00f56ab86d05 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p11-0x.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If a template-parameter of a class template has a default +// template-argument, each subsequent template-parameter shall either +// have a default template-argument supplied or be a template +// parameter pack. +template struct vector; + +template struct X2t; +template struct X2nt; +template class M = vector, template class... Metas> + struct X2tt; + +// If a template-parameter of a primary class template is a template +// parameter pack, it shall be the last template-parameter . +template +struct X0t; + +template +struct X0nt; + +template class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0tt; + +// [ Note: These are not requirements for function templates or class +// template partial specializations because template arguments can be +// deduced (14.8.2). -- end note] +template struct X1t; +template struct X1t { }; + +template struct X1nt; +template struct X1nt { }; + +// FIXME: Need template template argument packs! +// template class... Meta> struct X1tt; +// template class... Meta, template class M> +// struct X1tt { }; + +template +void f1t(X1t); + +template +void f1nt(X1nt); + +// FIXME: Need template template argument packs! +// template class... Meta, template class M> +// void f1tt(X1tt);