From patchwork Mon Apr 16 22:19:26 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/38543 (specialization of variadic function template) Date: Mon, 16 Apr 2012 12:19:26 -0000 From: Jason Merrill X-Patchwork-Id: 153001 Message-Id: <4F8C9AEE.1010708@redhat.com> To: gcc-patches List The old code that compares the number of parameter types doesn't work in the age of variadic templates. Instead, we should take the deduced template arguments, substitute them in, and see if the result is what we're looking for. Tested x86_64-pc-linux-gnu, applying to trunk. commit 84857b9698edb306e9659b1cc3a9f63829689db3 Author: Jason Merrill Date: Mon Apr 16 13:32:36 2012 -0400 PR c++/38543 * pt.c (determine_specialization): Instead of comparing the number of parms, check that tsubst gives the right answer. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 171acb7..92c2326 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1839,6 +1839,7 @@ determine_specialization (tree template_id, { tree decl_arg_types; tree fn_arg_types; + tree insttype; /* In case of explicit specialization, we need to check if the number of template headers appearing in the specialization @@ -1900,15 +1901,6 @@ determine_specialization (tree template_id, fn_arg_types = skip_artificial_parms_for (fn, fn_arg_types); - /* Check that the number of function parameters matches. - For example, - template void f(int i = 0); - template <> void f(); - The specialization f is invalid but is not caught - by get_bindings below. */ - if (list_length (fn_arg_types) != list_length (decl_arg_types)) - continue; - /* Function templates cannot be specializations; there are no partial specializations of functions. Therefore, if the type of DECL does not match FN, there is no @@ -1929,6 +1921,15 @@ determine_specialization (tree template_id, specialize TMPL will produce DECL. */ continue; + /* Make sure that the deduced arguments actually work. */ + insttype = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE); + if (insttype == error_mark_node) + continue; + fn_arg_types + = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype)); + if (!compparms (fn_arg_types, decl_arg_types)) + continue; + /* Save this template, and the arguments deduced. */ templates = tree_cons (targs, fn, templates); } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic131.C b/gcc/testsuite/g++.dg/cpp0x/variadic131.C new file mode 100644 index 0000000..3006f87 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic131.C @@ -0,0 +1,11 @@ +// PR c++/38543 +// { dg-do compile { target c++11 } } + +template< typename ... T > void foo( T ... args ); +template<> void foo( ){} +template<> void foo(int,double){} +int main() +{ + foo( 0, 0.0 ); + return 55; +}