]> granicus.if.org Git - clang/commitdiff
Implement proper parameter pack matching for non-type template
authorDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 16:01:49 +0000 (16:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 16:01:49 +0000 (16:01 +0000)
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
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp

index b86d7045b2f494621cbbe4908ffa2cf194bd81d9..f6354bf46daf82a7b5bd427e2d778a54041704fc 100644 (file)
@@ -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<
index a0c89f0fbd6f6c2d3607ef7bf96fa75235c85744..8e7e1eef4afc38757a4422253422e041eaaa0b5d 100644 (file)
@@ -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,
index 126a0961b1c1077e3afffecb551bff8f82714847..3fc774cbfad0c64da20179e1bf5672bba1e9f1d4 100644 (file)
@@ -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}}