https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119447

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
pop_nested_class assumes push_nested_class actually did something, but that is
not always the case:
void
push_nested_class (tree type)
{
  /* A namespace might be passed in error cases, like A::B:C.  */
  if (type == NULL_TREE
      || !CLASS_TYPE_P (type))
    return;

  push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type)));

  pushclass (type);
}

/* Undoes a push_nested_class call.  */

void
pop_nested_class (void)
{
  tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));

  popclass ();
  if (context && CLASS_TYPE_P (context))
    pop_nested_class ();
}

instantiate_template in particular does:
  if (DECL_CLASS_SCOPE_P (gen_tmpl))
    {
      tree ctx;
      if (!uses_template_parms (DECL_CONTEXT (tmpl)))
        /* If the context of the partially instantiated template is
           already non-dependent, then we might as well use it.  */
        ctx = DECL_CONTEXT (tmpl);
      else
        ctx = tsubst_entering_scope (DECL_CONTEXT (gen_tmpl), targ_ptr,
                                     complain, gen_tmpl);
      push_nested_class (ctx);
    }
...
  if (DECL_CLASS_SCOPE_P (gen_tmpl))
    pop_nested_class ();

uses_template_parms (DECL_CONTEXT (tmpl)) is true and tsubst_entering_scope
diagnoses and error and returns error_mark_node, so push_nested_class returns
early, but nothing tells the caller when it didn't do anything.

--- gcc/cp/pt.cc.jj     2025-03-23 10:24:27.462152570 +0100
+++ gcc/cp/pt.cc        2025-03-25 11:23:14.284793145 +0100
@@ -11955,7 +11955,7 @@ tsubst_friend_class (tree friend_tmpl, t

   if (TREE_CODE (context) == NAMESPACE_DECL)
     pop_nested_namespace (context);
-  else
+  else if (CLASS_TYPE_P (context))
     pop_nested_class ();

   return TREE_TYPE (tmpl);
@@ -22659,9 +22659,9 @@ instantiate_template (tree tmpl, tree or
       ++processing_template_decl;
       complain |= tf_partial;
     }
+  tree ctx = NULL_TREE;
   if (DECL_CLASS_SCOPE_P (gen_tmpl))
     {
-      tree ctx;
       if (!uses_template_parms (DECL_CONTEXT (tmpl)))
        /* If the context of the partially instantiated template is
           already non-dependent, then we might as well use it.  */
@@ -22698,7 +22698,7 @@ instantiate_template (tree tmpl, tree or
   /* Substitute template parameters to obtain the specialization.  */
   if (fndecl == NULL_TREE)
     fndecl = tsubst_decl (pattern, targ_ptr, complain,
/*use_spec_table=*/false);
-  if (DECL_CLASS_SCOPE_P (gen_tmpl))
+  if (ctx && CLASS_TYPE_P (ctx))
     pop_nested_class ();
   pop_from_top_level ();

fixes the ICE for me, but dunno if that is the right approach.

Reply via email to