aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-06-04 08:34:32 +0000
committerDouglas Gregor <dgregor@apple.com>2010-06-04 08:34:32 +0000
commita417b87e5d0f0508c7b18824d89d489bb55b7bd1 (patch)
tree0a459eb35d1e95730a0d99a2765efa87abb85683
parent4bde1e13d39e43581f7da872e4d7676ebf4a3ee7 (diff)
When checking for equality of template parameter lists, a template
type parameter pack is distinct from a template type parameter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105464 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td13
-rw-r--r--lib/Sema/SemaTemplate.cpp29
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp21
3 files changed, 60 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 0ba31aee2f..207b081cf7 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1234,6 +1234,7 @@ def err_template_param_different_kind : Error<
"%select{|template parameter }0redeclaration">;
def note_template_param_different_kind : Note<
"template parameter has a different kind in template argument">;
+
def err_template_nontype_parm_different_type : Error<
"template non-type parameter has a different type %0 in template "
"%select{|template parameter }1redeclaration">;
@@ -1606,6 +1607,18 @@ def err_template_param_pack_default_arg : Error<
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">;
+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">;
+def note_template_parameter_pack_here : Note<
+ "previous template %select{type|non-type|template}0 "
+ "parameter%select{| pack}1 declared here">;
+
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
def err_unexpected_namespace : Error<
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 40bbb15269..b02fc05892 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3237,9 +3237,32 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
return false;
}
- if (isa<TemplateTypeParmDecl>(*OldParm)) {
- // Okay; all template type parameters are equivalent (since we
- // know we're at the same index).
+ if (TemplateTypeParmDecl *OldTTP
+ = dyn_cast<TemplateTypeParmDecl>(*OldParm)) {
+ // Template type parameters are equivalent if either both are template
+ // type parameter packs or neither are (since we know we're at the same
+ // index).
+ TemplateTypeParmDecl *NewTTP = cast<TemplateTypeParmDecl>(*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)
+ << 0 << NewTTP->isParameterPack();
+ Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
+ << 0 << OldTTP->isParameterPack();
+ }
+ return false;
+ }
} else if (NonTypeTemplateParmDecl *OldNTTP
= dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
// The types of non-type template parameters must agree.
diff --git a/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp
new file mode 100644
index 0000000000..7352be2d72
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// Check for template type parameter pack (mis-)matches with template
+// type parameters.
+template<typename ...T> struct X0t;
+template<typename ...T> struct X0t;
+
+template<typename ...T> struct X1t; // expected-note{{previous template type parameter pack declared here}}
+template<typename T> struct X1t; // expected-error{{template type parameter conflicts with previous template type parameter pack}}
+
+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 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 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}}