re PR c++/49785 ([C++0x] ICE in coerce_template_parms)
authorJason Merrill <jason@redhat.com>
Tue, 19 Jul 2011 17:28:13 +0000 (13:28 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 19 Jul 2011 17:28:13 +0000 (13:28 -0400)
PR c++/49785
* pt.c (coerce_template_parms): Handle non-pack after pack.

From-SVN: r176472

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic114.C [new file with mode: 0644]

index f80f7b6916a328b2ccdde240f9ea46b1b64e9bdc..2f5be0ac1e53731283aa66c57f02d9035890f51e 100644 (file)
@@ -1,3 +1,8 @@
+2011-07-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/49785
+       * pt.c (coerce_template_parms): Handle non-pack after pack.
+
 2011-07-19  Richard Guenther  <rguenther@suse.de>
 
        * call.c (build_special_member_call): Use fold_build_pointer_plus.
index f34e1df818b553f626dbfaf6586716d56307fcc2..178685c40d48234eea5918b5f6ab7129d9199ba8 100644 (file)
@@ -6537,6 +6537,7 @@ coerce_template_parms (tree parms,
      subtract it from nparms to get the number of non-variadic
      parameters.  */
   int variadic_p = 0;
+  int post_variadic_parms = 0;
 
   if (args == error_mark_node)
     return error_mark_node;
@@ -6547,19 +6548,22 @@ coerce_template_parms (tree parms,
   for (parm_idx = 0; parm_idx < nparms; ++parm_idx)
     {
       tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
+      if (variadic_p)
+       ++post_variadic_parms;
       if (template_parameter_pack_p (tparm))
        ++variadic_p;
     }
 
   inner_args = INNERMOST_TEMPLATE_ARGS (args);
-  /* If there are 0 or 1 parameter packs, we need to expand any argument
-     packs so that we can deduce a parameter pack from some non-packed args
-     followed by an argument pack, as in variadic85.C.  If there are more
-     than that, we need to leave argument packs intact so the arguments are
-     assigned to the right parameter packs.  This should only happen when
-     dealing with a nested class inside a partial specialization of a class
-     template, as in variadic92.C.  */
-  if (variadic_p <= 1)
+  /* If there are no parameters that follow a parameter pack, we need to
+     expand any argument packs so that we can deduce a parameter pack from
+     some non-packed args followed by an argument pack, as in variadic85.C.
+     If there are such parameters, we need to leave argument packs intact
+     so the arguments are assigned properly.  This can happen when dealing
+     with a nested class inside a partial specialization of a class
+     template, as in variadic92.C, or when deducing a template parameter pack
+     from a sub-declarator, as in variadic114.C.  */
+  if (!post_variadic_parms)
     inner_args = expand_template_argument_pack (inner_args);
 
   nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
@@ -6574,7 +6578,7 @@ coerce_template_parms (tree parms,
        {
           if (variadic_p)
             {
-              --nparms;
+              nparms -= variadic_p;
              error ("wrong number of template arguments "
                     "(%d, should be %d or more)", nargs, nparms);
             }
index 1216d41ff435089e65f8c3939fc80263c81d9630..ea0fc853f18bc9f59fe650bd718621000d269cce 100644 (file)
@@ -1,3 +1,8 @@
+2011-07-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/49785
+       * g++.dg/cpp0x/variadic114.C: New.
+
 2011-07-19  Tobias Burnus  <burnus@net-b.de>
 
        * gfortran.dg/coarray_args_1.f90: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic114.C b/gcc/testsuite/g++.dg/cpp0x/variadic114.C
new file mode 100644 (file)
index 0000000..3ffede5
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/49785
+// { dg-options -std=c++0x }
+
+template <typename, typename ...> struct B { };
+template <typename> class A;
+
+template <typename R, typename ... S>
+struct A <R (S ...)> : public B <R, S ...>
+{
+  struct C {};
+  template <typename D> A (D, C = C ()) { }
+  R operator () (...);
+};
+
+template <typename R, typename ... S, typename T>
+auto operator >> (A <R (S ...)>, T)->A <R (S ...)>
+{
+  []() {};
+}
+
+int
+main ()
+{
+  A <int (int, int)> a = [](int, int) {};
+  auto b = []{};
+  (a >> b) (3, 5);
+}