From f457c1a0a46d11623c3d4594b57dff7f5a1151da Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 5 Jan 2011 16:01:49 +0000 Subject: [PATCH] Implement proper parameter pack matching for non-type template parameters and template template parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122875 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 14 +++--- lib/Sema/SemaTemplate.cpp | 43 +++++++++++++++++++ .../temp.variadic/parameter-matching.cpp | 18 +++++--- 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b86d7045b2..f6354bf46d 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1821,15 +1821,15 @@ def err_template_param_pack_must_be_last_template_parameter : Error< "template parameter pack must be the last template parameter">; def err_template_parameter_pack_non_pack : Error< - "template %select{type|non-type|template}0 parameter%select{| pack}1 " - "conflicts with previous template %select{type|non-type|template}0 " - "parameter%select{ pack|}1">; + "%select{template type|non-type template|template template}0 parameter" + "%select{| pack}1 conflicts with previous %select{template type|" + "non-type template|template template}0 parameter%select{ pack|}1">; def note_template_parameter_pack_non_pack : Note< - "template %select{type|non-type|template}0 parameter%select{| pack}1 " - "does not match template %select{type|non-type|template}0 " - "parameter%select{ pack|}1 in template argument">; + "%select{template type|non-type template|template template}0 parameter" + "%select{| pack}1 does not match %select{template type|non-type template" + "|template template}0 parameter%select{ pack|}1 in template argument">; def note_template_parameter_pack_here : Note< - "previous template %select{type|non-type|template}0 " + "previous %select{template type|non-type template|template template}0 " "parameter%select{| pack}1 declared here">; def err_unexpanded_parameter_pack_0 : Error< diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index a0c89f0fbd..8e7e1eef4a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3687,6 +3687,27 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, NonTypeTemplateParmDecl *NewNTTP = cast(*NewParm); + if (OldNTTP->isParameterPack() != NewNTTP->isParameterPack()) { + // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that + // allow one to match a template parameter pack in the template + // parameter list of a template template parameter to one or more + // template parameters in the template parameter list of the + // corresponding template template argument. + if (Complain) { + unsigned NextDiag = diag::err_template_parameter_pack_non_pack; + if (TemplateArgLoc.isValid()) { + Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_parameter_pack_non_pack; + } + Diag(NewNTTP->getLocation(), NextDiag) + << 1 << NewNTTP->isParameterPack(); + Diag(OldNTTP->getLocation(), diag::note_template_parameter_pack_here) + << 1 << OldNTTP->isParameterPack(); + } + return false; + } + // If we are matching a template template argument to a template // template parameter and one of the non-type template parameter types // is dependent, then we must wait until template instantiation time @@ -3723,6 +3744,28 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, = cast(*OldParm); TemplateTemplateParmDecl *NewTTP = cast(*NewParm); + + if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) { + // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that + // allow one to match a template parameter pack in the template + // parameter list of a template template parameter to one or more + // template parameters in the template parameter list of the + // corresponding template template argument. + if (Complain) { + unsigned NextDiag = diag::err_template_parameter_pack_non_pack; + if (TemplateArgLoc.isValid()) { + Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_parameter_pack_non_pack; + } + Diag(NewTTP->getLocation(), NextDiag) + << 2 << NewTTP->isParameterPack(); + Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here) + << 2 << OldTTP->isParameterPack(); + } + return false; + } + if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(), OldTTP->getTemplateParameters(), Complain, diff --git a/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp index 126a0961b1..3fc774cbfa 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp @@ -11,13 +11,17 @@ template struct X1t; // expected-error{{template type parameter conf template struct X2t; // expected-note{{previous template type parameter declared here}} template struct X2t; // expected-error{{template type parameter pack conflicts with previous template type parameter}} -template class> struct X0tt; -template class> struct X0tt; +template class> struct X0t_intt; +template class> struct X0t_intt; -template class> struct X1tt; // expected-note{{previous template type parameter pack declared here}} -template class> struct X1tt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} +template class> struct X1t_intt; // expected-note{{previous template type parameter pack declared here}} +template class> struct X1t_intt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} -template class> struct X2tt; // expected-note{{previous template type parameter declared here}} -template class> struct X2tt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} +template class> struct X2t_intt; // expected-note{{previous template type parameter declared here}} +template class> struct X2t_intt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} -// FIXME: Add checks for non-type template parameter packs, template parameter packs +template struct X1nt; // expected-note{{previous non-type template parameter pack declared here}} +template struct X1nt; // expected-error{{non-type template parameter conflicts with previous non-type template parameter pack}} + +template class> class X1tt; // expected-note{{previous template template parameter declared here}} +template class...> class X1tt; // expected-error{{template template parameter pack conflicts with previous template template parameter}} -- 2.50.1