https://gcc.gnu.org/g:d025b6880cde2cb2063b4d34546cdd70e5526e74

commit r14-11434-gd025b6880cde2cb2063b4d34546cdd70e5526e74
Author: Patrick Palka <ppa...@redhat.com>
Date:   Sat Mar 22 10:18:07 2025 -0400

    c++: ICE w/ dependently scoped template friend [PR119378]
    
    Here we ICE during instantiation of the dependently scoped template
    friend
    
      template<int N>
      struct<class T>
      friend class A<N>::B;
    
    ultimately because processing_template_decl isn't set during
    substitution into the A<N> scope.  Since it's naturally a partial
    substitution, we need to make sure the flag is set.
    
    For GCC 15, this is already fixed similarly by r15-123.
    
            PR c++/119378
    
    gcc/cp/ChangeLog:
    
            * pt.cc (tsubst) <case UNBOUND_CLASS_TEMPLATE>: Set
            processing_template_decl when substituting the context.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/friend85.C: New test.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/pt.cc                             |  2 ++
 gcc/testsuite/g++.dg/template/friend85.C | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ca34ed75d659..2efc7eb19e87 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16946,8 +16946,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
 
     case UNBOUND_CLASS_TEMPLATE:
       {
+       ++processing_template_decl;
        tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
                                     in_decl, /*entering_scope=*/1);
+       --processing_template_decl;
        tree name = TYPE_IDENTIFIER (t);
        tree parm_list = DECL_TEMPLATE_PARMS (TYPE_NAME (t));
 
diff --git a/gcc/testsuite/g++.dg/template/friend85.C 
b/gcc/testsuite/g++.dg/template/friend85.C
new file mode 100644
index 000000000000..5cf839111931
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend85.C
@@ -0,0 +1,16 @@
+// PR c++/119378
+
+template<int N>
+struct A {
+  template<class T>
+  struct B;
+};
+
+template<class U>
+struct C {
+  template<int N>
+  template<class T>
+  friend class A<N>::B;
+};
+
+template struct C<int>;

Reply via email to