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 <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
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. */
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. */
--- /dev/null
+// { 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>&) {}
--- /dev/null
+// { dg-additional-options "-fmodules -Wno-global-module" }
+// { dg-module-cmi M }
+
+export module M;
+export import :part;