Patchwork C++ PATCH for c++/55220 (ICE with non-deducible parameter pack)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 14, 2013, 10:43 p.m.
Message ID <511D688C.7030104@redhat.com>
Download mbox | patch
Permalink /patch/220538/
State New
Headers show

Comments

Jason Merrill - Feb. 14, 2013, 10:43 p.m.
This testcase is well-formed, even though it doesn't do what the user 
was trying to accomplish.  In Tuple<Head..., T> the use of a pack 
expansion not at the end of the list makes the whole argument list a 
non-deduced context, so we should get out early before it confuses us.

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

Patch

commit 48b50b5ac0b2f36d6b2f00c51862fe5461119eca
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Feb 14 12:00:30 2013 -0500

    	PR c++/55220
    	* pt.c (unify): A pack expansion that is not the last template
    	argument makes the entire template argument list non-deduced.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e88ea85..440df1e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16548,6 +16548,14 @@  unify (tree tparms, tree targs, tree parm, tree arg, int strict,
                 && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
               parm_variadic_p = 1;
             
+             for (i = 0; i < len - parm_variadic_p; ++i)
+	       /* If the template argument list of P contains a pack
+		  expansion that is not the last template argument, the
+		  entire template argument list is a non-deduced
+		  context.  */
+	       if (PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, i)))
+		 return unify_success (explain_p);
+
             if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
               return unify_too_few_arguments (explain_p,
 					      TREE_VEC_LENGTH (argvec), len);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce2.C
new file mode 100644
index 0000000..a82a098
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce2.C
@@ -0,0 +1,25 @@ 
+// PR c++/55220
+// { dg-do compile { target c++11 } }
+
+template <typename ...> struct something_like_tuple
+{
+
+};
+
+template <typename, typename> struct is_last
+{
+  static const bool value = false;
+};
+
+// Head is non-deducible, so this can't work as the user intended
+template <typename T, template <typename ...> class Tuple, typename ... Head>
+struct is_last<T, Tuple<Head ..., T>>
+{
+  static const bool value = true;
+};
+
+#define SA(X) static_assert (X, #X)
+
+typedef something_like_tuple<char, int, float> something_like_tuple_t;
+SA ((is_last<float, something_like_tuple_t>::value == false));
+SA ((is_last<int, something_like_tuple_t>::value == false));