On 12/1/25 7:18 PM, Nathaniel Shead wrote:
I bumped into this while reducing a different issue. Bootstrapped and tested (so far just modules.exp) on x86_64-pc-linux-gnu, OK for trunk if full regtest passes?
OK.
-- >8 -- 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]> --- 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(+) create mode 100644 gcc/testsuite/g++.dg/modules/friend-12_a.C create mode 100644 gcc/testsuite/g++.dg/modules/friend-12_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index e5668be4786..cae45224c9e 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 00000000000..827c74b8f58 --- /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 00000000000..7eb7014660f --- /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;
