Here an earlier fix of mine related to -fnew-ttp-matching caused us to silently discard a pack expansion argument that will be ill-formed if it's ever non-empty. It would be correct to reject this template definition immediately, since a variadic template that is well-formed only for empty packs is ill-formed (no diagnostic required), but my attempts to do that while still allowing variadic-ttp3a.C have run into trouble, so I don't think this is the time to keep poking at it.
But if we are going to allow this in the template, we need to remember the pack expansion argument so we can reject it as needed at instantiation time. Tested x86_64-pc-linux-gnu, applied to trunk.
commit 8aaa042bd0a97034d42262ff0efeec9979f13fbe Author: Jason Merrill <ja...@redhat.com> Date: Tue Mar 27 19:18:19 2018 -0400 PR c++/85093 - too many template args with pack expansion. * pt.c (coerce_template_parms): Keep pack expansion args that will need to be empty. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 40ddf9ec989..284eaf3cab6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8497,6 +8497,22 @@ coerce_template_parms (tree parms, goto bad_nargs; } + if (arg_idx < nargs) + { + /* We had some pack expansion arguments that will only work if the packs + are empty, but wait until instantiation time to complain. + See variadic-ttp3.C. */ + int len = nparms + (nargs - arg_idx); + tree args = make_tree_vec (len); + int i = 0; + for (; i < nparms; ++i) + TREE_VEC_ELT (args, i) = TREE_VEC_ELT (new_inner_args, i); + for (; i < len; ++i, ++arg_idx) + TREE_VEC_ELT (args, i) = TREE_VEC_ELT (inner_args, + arg_idx - pack_adjust); + new_inner_args = args; + } + if (lost) { gcc_assert (!(complain & tf_error) || seen_error ()); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-empty1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-empty1.C new file mode 100644 index 00000000000..42daeaa3dcb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-empty1.C @@ -0,0 +1,13 @@ +// PR c++/85093 +// { dg-do compile { target c++11 } } + +template<class V> class A {}; + +template<class V, class... G> class B { + typedef A<V,G...> AB; // { dg-error "arguments" } + AB ab; +}; + +int main() { + B<int,double> b; +}