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

Reply via email to