aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-05 16:01:49 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-05 16:01:49 +0000
commitf457c1a0a46d11623c3d4594b57dff7f5a1151da (patch)
tree4ab5d2129b1487c709bc44b1be35c1bfdc27fa85
parent61c4d28e36cd3f1be392cb77f07436d1fa6b0f9f (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td14
-rw-r--r--lib/Sema/SemaTemplate.cpp43
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp18
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<NonTypeTemplateParmDecl>(*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<TemplateTemplateParmDecl>(*OldParm);
TemplateTemplateParmDecl *NewTTP
= cast<TemplateTemplateParmDecl>(*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<typename T> struct X1t; // expected-error{{template type parameter conf
template<typename T> struct X2t; // expected-note{{previous template type parameter declared here}}
template<typename ...T> struct X2t; // expected-error{{template type parameter pack conflicts with previous template type parameter}}
-template<template<typename ...T> class> struct X0tt;
-template<template<typename ...T> class> struct X0tt;
+template<template<typename ...T> class> struct X0t_intt;
+template<template<typename ...T> class> struct X0t_intt;
-template<template<typename ...T> class> struct X1tt; // expected-note{{previous template type parameter pack declared here}}
-template<template<typename T> class> struct X1tt; // expected-error{{template type parameter conflicts with previous template type parameter pack}}
+template<template<typename ...T> class> struct X1t_intt; // expected-note{{previous template type parameter pack declared here}}
+template<template<typename T> class> struct X1t_intt; // expected-error{{template type parameter conflicts with previous template type parameter pack}}
-template<template<typename T> class> struct X2tt; // expected-note{{previous template type parameter declared here}}
-template<template<typename ...T> class> struct X2tt; // expected-error{{template type parameter pack conflicts with previous template type parameter}}
+template<template<typename T> class> struct X2t_intt; // expected-note{{previous template type parameter declared here}}
+template<template<typename ...T> 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<int ...Values> struct X1nt; // expected-note{{previous non-type template parameter pack declared here}}
+template<int Values> struct X1nt; // expected-error{{non-type template parameter conflicts with previous non-type template parameter pack}}
+
+template<template<class T> class> class X1tt; // expected-note{{previous template template parameter declared here}}
+template<template<class T> class...> class X1tt; // expected-error{{template template parameter pack conflicts with previous template template parameter}}