PR c++/71834 - template-id with too few arguments.
authorJason Merrill <jason@redhat.com>
Mon, 19 Mar 2018 20:32:57 +0000 (16:32 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 19 Mar 2018 20:32:57 +0000 (16:32 -0400)
* pt.c (coerce_template_parms): Check fixed_parameter_pack_p.

From-SVN: r258659

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

index 12aaf135294c898ee8216495c96dbe9350a96975..194b46890825d186252a063c58f72abaf7422dff 100644 (file)
@@ -1,3 +1,8 @@
+2018-03-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/71834 - template-id with too few arguments.
+       * pt.c (coerce_template_parms): Check fixed_parameter_pack_p.
+
 2018-03-19  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/84835
index fba65b4abdf74f2631aad90144d01eb91de003be..086cdc20781b7ecd173d40dbce7987a23d0ae55c 100644 (file)
@@ -8235,6 +8235,11 @@ coerce_template_parms (tree parms,
   int variadic_args_p = 0;
   int post_variadic_parms = 0;
 
+  /* Adjustment to nparms for fixed parameter packs.  */
+  int fixed_pack_adjust = 0;
+  int fixed_packs = 0;
+  int missing = 0;
+
   /* Likewise for parameters with default arguments.  */
   int default_p = 0;
 
@@ -8279,6 +8284,7 @@ coerce_template_parms (tree parms,
              || (TREE_VEC_ELT (parms, nargs) != error_mark_node
                   && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
     {
+    bad_nargs:
       if (complain & tf_error)
        {
           if (variadic_p || default_p)
@@ -8390,11 +8396,17 @@ coerce_template_parms (tree parms,
              lost++;
              /* We are done with all of the arguments.  */
              arg_idx = nargs;
+             break;
            }
          else
            {
              pack_adjust = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) - 1;
              arg_idx += pack_adjust;
+             if (fixed_parameter_pack_p (TREE_VALUE (parm)))
+               {
+                 ++fixed_packs;
+                 fixed_pack_adjust += pack_adjust;
+               }
            }
           
           continue;
@@ -8452,12 +8464,18 @@ coerce_template_parms (tree parms,
            error ("template argument %d is invalid", arg_idx + 1);
        }
       else if (!arg)
-        /* This only occurs if there was an error in the template
-           parameter list itself (which we would already have
-           reported) that we are trying to recover from, e.g., a class
-           template with a parameter list such as
-           template<typename..., typename>.  */
-       ++lost;
+       {
+         /* This can occur if there was an error in the template
+            parameter list itself (which we would already have
+            reported) that we are trying to recover from, e.g., a class
+            template with a parameter list such as
+            template<typename..., typename> (cpp0x/variadic150.C).  */
+         ++lost;
+
+         /* This can also happen with a fixed parameter pack (71834).  */
+         if (arg_idx >= nargs)
+           ++missing;
+       }
       else
        arg = convert_template_argument (TREE_VALUE (parm),
                                         arg, new_args, complain, 
@@ -8470,20 +8488,20 @@ coerce_template_parms (tree parms,
   cp_unevaluated_operand = saved_unevaluated_operand;
   c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
 
-  if (variadic_p && arg_idx < nargs)
+  if (missing || arg_idx < nargs - variadic_args_p)
     {
-      if (complain & tf_error)
-       {
-         error ("wrong number of template arguments "
-                "(%d, should be %d)", nargs, arg_idx);
-         if (in_decl)
-           error ("provided for %q+D", in_decl);
-       }
-      return error_mark_node;
+      /* If we had fixed parameter packs, we didn't know how many arguments we
+        actually needed earlier; now we do.  */
+      nparms += fixed_pack_adjust;
+      variadic_p -= fixed_packs;
+      goto bad_nargs;
     }
 
   if (lost)
-    return error_mark_node;
+    {
+      gcc_assert (!(complain & tf_error) || seen_error ());
+      return error_mark_node;
+    }
 
   if (CHECKING_P && !NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
     SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nested3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nested3.C
new file mode 100644 (file)
index 0000000..381ff73
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/71834
+// { dg-do compile { target c++11 } }
+
+template < typename ... Ts > struct A 
+{
+  template < Ts ..., typename U > struct B {};
+};
+
+// should be, e.g.: A < int >::B < 0, int > e; 
+A < int >::B < 0 > e;     // { dg-error "wrong number of template arguments" }