commit 6de84fdaef34cd48649ed501958aa3c93b289f7e Author: Jason Merrill Date: Mon Jun 26 14:35:52 2017 -0400 PR c++/81215 - deduction failure with variadic TTP. * pt.c (unify_bound_ttp_args): Restore old logic for C++14 and down. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 392fba0..43f9ca8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7170,26 +7170,68 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg, parmvec = expand_template_argument_pack (parmvec); argvec = expand_template_argument_pack (argvec); - tree nparmvec = parmvec; if (flag_new_ttp) { /* In keeping with P0522R0, adjust P's template arguments to apply to A's template; then flatten it again. */ + tree nparmvec = parmvec; nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none); nparmvec = expand_template_argument_pack (nparmvec); + + if (unify (tparms, targs, nparmvec, argvec, + UNIFY_ALLOW_NONE, explain_p)) + return 1; + + /* If the P0522 adjustment eliminated a pack expansion, deduce + empty packs. */ + if (flag_new_ttp + && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec) + && unify_pack_expansion (tparms, targs, parmvec, argvec, + DEDUCE_EXACT, /*sub*/true, explain_p)) + return 1; } + else + { + /* Deduce arguments T, i from TT or TT. + We check each element of PARMVEC and ARGVEC individually + rather than the whole TREE_VEC since they can have + different number of elements, which is allowed under N2555. */ + + int len = TREE_VEC_LENGTH (parmvec); + + /* Check if the parameters end in a pack, making them + variadic. */ + int parm_variadic_p = 0; + if (len > 0 + && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1))) + parm_variadic_p = 1; - if (unify (tparms, targs, nparmvec, argvec, - UNIFY_ALLOW_NONE, explain_p)) - return 1; - - /* If the P0522 adjustment eliminated a pack expansion, deduce - empty packs. */ - if (flag_new_ttp - && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec) - && unify_pack_expansion (tparms, targs, parmvec, argvec, - DEDUCE_EXACT, /*sub*/true, explain_p)) - return 1; + for (int 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); + + for (int i = 0; i < len - parm_variadic_p; ++i) + if (unify (tparms, targs, + TREE_VEC_ELT (parmvec, i), + TREE_VEC_ELT (argvec, i), + UNIFY_ALLOW_NONE, explain_p)) + return 1; + + if (parm_variadic_p + && unify_pack_expansion (tparms, targs, + parmvec, argvec, + DEDUCE_EXACT, + /*subr=*/true, explain_p)) + return 1; + } return 0; } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C new file mode 100644 index 0000000..0dbe904 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C @@ -0,0 +1,16 @@ +// PR c++/81215 +// { dg-do compile { target c++11 } } + +template struct X { }; +template struct set { }; + +template class C> +void bar (const X>&) +{ +} + +void +foo (X>& x) +{ + bar (x); +}