Some syntactically invalid code can confuse the compiler into trying to define a specialization while processing_template_parmlist != 0, during which there is a dummy parameter level (a TREE_VEC of length 0) on current_template_parms which the TEMPLATE_DECL of the specialization then inherits. This dummy parameter level is expected to appear only on the template parms of a TEMPLATE_TEMPLATE_PARM so its appearance on a TEMPLATE_DECL (of the bogus specialization) eventually causes an ICE. >From what I understand, a template specialization can not possibly be defined from inside a template parameter list so this patch avoids the ICE by avoiding to generate the bogus specialization in the first place. Does this look OK to commit after bootstrap + regtesting?
gcc/cp/ChangeLog: PR c++/77639 * pt.c (maybe_process_partial_specialization): Don't try defining a specialization when processing_template_parmlist. gcc/testsuite/ChangeLog: PR c++/77639 * g++.dg/template/error-recovery4.C: New test. --- gcc/cp/pt.c | 8 ++++++++ gcc/testsuite/g++.dg/template/error-recovery4.C | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/g++.dg/template/error-recovery4.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 29d8beb..c1b3d5b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -962,6 +962,14 @@ maybe_process_partial_specialization (tree type) if (tree t = maybe_new_partial_specialization (type)) { + if (processing_template_parmlist) + { + /* Some syntactically invalid code can confuse the compiler into + defining a specialization from inside a template parameter + list. Bail out now so that we won't ICE later. */ + gcc_assert (seen_error ()); + return error_mark_node; + } if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (t)) && !at_namespace_scope_p ()) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/template/error-recovery4.C b/gcc/testsuite/g++.dg/template/error-recovery4.C new file mode 100644 index 0000000..1725d87 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error-recovery4.C @@ -0,0 +1,5 @@ +// PR c++/77639 + +template <class, int, class, int> struct B {}; +template <class T, int a, class U struct B<int, 2, char, 1> {}; // { dg-error "" } +B<int, 2, char, 1> i; -- 2.10.0.87.g1cd26dd