On 3/21/25 3:46 PM, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
14/13/12 (since it was reported against GCC 12)? This old regression is
already fixed on trunk by r15-123 which contains this change.
OK.
-- >8 --
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 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.
---
gcc/cp/pt.cc | 2 ++
gcc/testsuite/g++.dg/template/friend85.C | 16 ++++++++++++++++
2 files changed, 18 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/template/friend85.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ca34ed75d65..2efc7eb19e8 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 00000000000..5cf83911193
--- /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>;