In the wg21.link/P0522 change to template template parameter matching, we ran into trouble with this testcase: when we try to form TTC<TA...>, we need to convert TA to TC, and try to tsubst TC to produce the real desired type. But trying to look up TC in the args for TTC fails, and indeed makes no sense. Even if we passed in more args somehow, what we have in outer_args are args for A, not for C, so that wouldn't help.
I dealt with this situation by recognizing that we are dealing with multiple levels of template parms and only have a single level of template args, so we can't possibly get the right answer, so we shouldn't do any substitution. Tested x86_64-pc-linux-gnu, applying to trunk.
commit 31437c878831d15bbccbd8a891a074aacfdeec10 Author: Jason Merrill <ja...@redhat.com> Date: Wed Mar 14 11:44:50 2018 -0400 PR c++/83916 - ICE with template template parameters. * pt.c (convert_template_argument): Don't substitute into type of non-type parameter if we don't have enough arg levels. (unify): Likewise. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d720c33cf0a..14321816cde 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7974,7 +7974,11 @@ convert_template_argument (tree parm, { tree t = TREE_TYPE (parm); - if (tree a = type_uses_auto (t)) + if (TEMPLATE_PARM_LEVEL (get_template_parm_index (parm)) + > TMPL_ARGS_DEPTH (args)) + /* We don't have enough levels of args to do any substitution. This + can happen in the context of -fnew-ttp-matching. */; + else if (tree a = type_uses_auto (t)) { t = do_auto_deduction (t, arg, a, complain, adc_unify, args); if (t == error_mark_node) @@ -21224,14 +21228,22 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, template-parameter exactly, except that a template-argument deduced from an array bound may be of any integral type. The non-type parameter might use already deduced type parameters. */ - ++processing_template_decl; - tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE); - --processing_template_decl; - if (tree a = type_uses_auto (tparm)) + tparm = TREE_TYPE (parm); + if (TEMPLATE_PARM_LEVEL (parm) > TMPL_ARGS_DEPTH (targs)) + /* We don't have enough levels of args to do any substitution. This + can happen in the context of -fnew-ttp-matching. */; + else { - tparm = do_auto_deduction (tparm, arg, a, complain, adc_unify); - if (tparm == error_mark_node) - return 1; + ++processing_template_decl; + tparm = tsubst (tparm, targs, tf_none, NULL_TREE); + --processing_template_decl; + + if (tree a = type_uses_auto (tparm)) + { + tparm = do_auto_deduction (tparm, arg, a, complain, adc_unify); + if (tparm == error_mark_node) + return 1; + } } if (!TREE_TYPE (arg)) diff --git a/gcc/testsuite/g++.dg/template/ttp31.C b/gcc/testsuite/g++.dg/template/ttp31.C new file mode 100644 index 00000000000..ff3f1f5c3ac --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ttp31.C @@ -0,0 +1,10 @@ +// PR c++/83916 +// { dg-do compile { target c++11 } } + +template<class TA, + template<TA...> class TTA, TA... VA> +struct A { }; + +template<class UC, class TC, + template<TC...> class TTC, TC... VC> +struct C : A<TC, TTC, VC...> { }; diff --git a/gcc/testsuite/g++.dg/template/ttp32.C b/gcc/testsuite/g++.dg/template/ttp32.C new file mode 100644 index 00000000000..a96a62d332f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ttp32.C @@ -0,0 +1,10 @@ +// PR c++/83916 +// { dg-do compile { target c++17 } } + +template<class TA, + template<auto...> class TTA, TA... VA> +struct A { }; + +template<class UC, class TC, + template<auto...> class TTC, TC... VC> +struct C : A<TC, TTC, VC...> { };