Patchwork C++ PATCH for c++/53862 (rejects-valid variadic templates)

login
register
mail settings
Submitter Jason Merrill
Date July 6, 2012, 3:42 p.m.
Message ID <4FF70783.2020107@redhat.com>
Download mbox | patch
Permalink /patch/169485/
State New
Headers show

Comments

Jason Merrill - July 6, 2012, 3:42 p.m.
tsubst doesn't handle pack expansions directly; any place where a pack 
expansion is valid needs to test for them and call 
tsubst_pack_expansion.  Here, the code for testing whether a non-deduced 
template argument is relevant to the argument types was failing to do 
so.  Conveniently, we already have a tsubst_arg_types function, so we 
can just call it.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 6c2eeaf17d04ff248f69f7ed54f6d1905a759048
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jul 6 10:25:16 2012 -0400

    	PR c++/53862
    	* pt.c (tsubst_arg_types): Add "end" parameter.
    	(check_undeduced_parms): Use it.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index df5d1f6..72b0c4f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -171,7 +171,7 @@  static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
 static void regenerate_decl_from_template (tree, tree);
 static tree most_specialized_class (tree, tree, tsubst_flags_t);
 static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
-static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
 static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
 static bool check_specialization_scope (void);
 static tree process_partial_specialization (tree);
@@ -10500,11 +10500,14 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
   return r;
 }
 
-/* Substitute into the ARG_TYPES of a function type.  */
+/* Substitute into the ARG_TYPES of a function type.
+   If END is a TREE_CHAIN, leave it and any following types
+   un-substituted.  */
 
 static tree
 tsubst_arg_types (tree arg_types,
 		  tree args,
+		  tree end,
 		  tsubst_flags_t complain,
 		  tree in_decl)
 {
@@ -10514,11 +10517,11 @@  tsubst_arg_types (tree arg_types,
   tree expanded_args = NULL_TREE;
   tree default_arg;
 
-  if (!arg_types || arg_types == void_list_node)
+  if (!arg_types || arg_types == void_list_node || arg_types == end)
     return arg_types;
 
   remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
-					  args, complain, in_decl);
+					  args, end, complain, in_decl);
   if (remaining_arg_types == error_mark_node)
     return error_mark_node;
 
@@ -10643,7 +10646,7 @@  tsubst_function_type (tree t,
     }
 
   /* Substitute the argument types.  */
-  arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args,
+  arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
 				complain, in_decl);
   if (arg_types == error_mark_node)
     return error_mark_node;
@@ -16757,12 +16760,9 @@  check_undeduced_parms (tree targs, tree args, tree end)
       }
   if (found)
     {
-      for (; args != end; args = TREE_CHAIN (args))
-	{
-	  tree substed = tsubst (TREE_VALUE (args), targs, tf_none, NULL_TREE);
-	  if (substed == error_mark_node)
-	    return true;
-	}
+      tree substed = tsubst_arg_types (args, targs, end, tf_none, NULL_TREE);
+      if (substed == error_mark_node)
+	return true;
     }
   return false;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic134.C b/gcc/testsuite/g++.dg/cpp0x/variadic134.C
new file mode 100644
index 0000000..d4181b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic134.C
@@ -0,0 +1,17 @@ 
+// PR c++/53862
+// { dg-do compile { target c++11 } }
+
+typedef unsigned long size_t;
+
+template<typename> struct is_scalar { static const bool value = true; };
+template<bool, typename T> struct enable_if { typedef T type; };
+
+template <size_t N, typename... Args>
+void f(Args...) {}
+
+template <size_t N, typename T, typename... Args>
+typename enable_if<is_scalar<T>::value, void>::type f(T, Args...) {}
+
+int main() {
+    f<1>(1);
+}