https://gcc.gnu.org/g:4247fc98bd910ff8af8bae2aec0dfc256fdde585

commit r16-5812-g4247fc98bd910ff8af8bae2aec0dfc256fdde585
Author: Nathaniel Shead <[email protected]>
Date:   Tue Dec 2 00:43:18 2025 +1100

    c++/modules: Stream DECL_CHAIN for decl_specialization_friend_p functions
    
    r16-5298 attached the owning class for a friend template specialisation
    on its DECL_CHAIN.  However we don't stream DECL_CHAIN in general to
    avoid walking into unrelated entities on the scope chain; this patch
    adds a special case for these functions to ensure we don't lose this
    information.
    
    Ideally this would occur in trees_{out,in}::core_vals, but we can't
    check decl_specialization_friend_p until after DECL_TEMPLATE_INFO has
    been streamed, hence the slightly unusual placement.
    
    gcc/cp/ChangeLog:
    
            * module.cc (trees_out::lang_decl_vals): Stream DECL_CHAIN for
            decl_specialization_friend_p functions.
            (trees_in::lang_decl_vals): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/friend-12_a.C: New test.
            * g++.dg/modules/friend-12_b.C: New test.
    
    Signed-off-by: Nathaniel Shead <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/module.cc                           |  8 ++++++++
 gcc/testsuite/g++.dg/modules/friend-12_a.C | 11 +++++++++++
 gcc/testsuite/g++.dg/modules/friend-12_b.C |  5 +++++
 3 files changed, 24 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 91e305c280b7..042b029a036e 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -7524,6 +7524,12 @@ trees_out::lang_decl_vals (tree t)
 
        WT (access);
       }
+      /* A friend template specialisation stashes its owning class on its
+        DECL_CHAIN; we need to reconstruct this, but it needs to happen
+        after we stream the template_info so readers can know this is such
+        an entity.  */
+      if (decl_specialization_friend_p (t))
+       WT (t->common.chain);
       break;
 
     case lds_ns:  /* lang_decl_ns.  */
@@ -7593,6 +7599,8 @@ trees_in::lang_decl_vals (tree t)
     lds_min:
       RT (lang->u.min.template_info);
       RT (lang->u.min.access);
+      if (decl_specialization_friend_p (t))
+       RT (t->common.chain);
       break;
 
     case lds_ns:  /* lang_decl_ns.  */
diff --git a/gcc/testsuite/g++.dg/modules/friend-12_a.C 
b/gcc/testsuite/g++.dg/modules/friend-12_a.C
new file mode 100644
index 000000000000..827c74b8f58b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-12_a.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules -Wno-global-module" }
+// { dg-module-cmi M:part }
+
+module;
+template <typename T> struct basic_streambuf;
+template <typename T> void __copy_streambufs_eof(basic_streambuf<T>*);
+template <typename T> struct basic_streambuf {
+  friend void __copy_streambufs_eof<>(basic_streambuf*);
+};
+export module M:part;
+void foo(basic_streambuf<char>&) {}
diff --git a/gcc/testsuite/g++.dg/modules/friend-12_b.C 
b/gcc/testsuite/g++.dg/modules/friend-12_b.C
new file mode 100644
index 000000000000..7eb7014660f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-12_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules -Wno-global-module" }
+// { dg-module-cmi M }
+
+export module M;
+export import :part;

Reply via email to