diff mbox

C++ PATCH for c++/38543 (specialization of variadic function template)

Message ID 4F8C9AEE.1010708@redhat.com
State New
Headers show

Commit Message

Jason Merrill April 16, 2012, 10:19 p.m. UTC
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.
diff mbox

Patch

commit 84857b9698edb306e9659b1cc3a9f63829689db3
Author: Jason Merrill <jason@redhat.com>
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 <class T> void f(int i = 0);
-	       template <> void f<int>();
-	     The specialization f<int> 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;
+}