Here when lazily loading the binding for f at parse time from the template g, processing_template_decl is set and thus the call to note_vague_linkage_fn from module_state::read_cluster has no effect, and we never push f onto deferred_fns and end up never emitting its definition.
ISTM the behavior of the lazy loading machinery shouldn't be sensitive to whether we're inside a template, and therefore we should probably be clearing processing_template_decl somewhere e.g in lazy_load_binding. This is sufficient to fix the testcase. But it also seems the processing_template_decl test in note_vague_linkage_fn, added by r8-7539-g977bc3ee11383e for PR84973, is perhaps too strong: if the intent is to avoid deferring output for uninstantiated templates, we should make sure that DECL in question is an uninstantiated template by checking e.g. value_dependent_expression_p. This too is sufficient to fix the testcase (since f isn't a template) and survives bootstrap and regtest. Does one or the other approach look like the correct fix for this PR? PR c++/99377 gcc/cp/ChangeLog: * decl2.cc (note_vague_linkage_fn): Relax processing_template_decl test to value_dependent_expression_p. * module.cc (lazy_load_binding): Clear processing_template_decl. gcc/testsuite/ChangeLog: * g++.dg/modules/pr99377-2_a.C: New test. * g++.dg/modules/pr99377-2_b.C: New test. --- gcc/cp/decl2.cc | 2 +- gcc/cp/module.cc | 2 ++ gcc/testsuite/g++.dg/modules/pr99377-2_a.C | 5 +++++ gcc/testsuite/g++.dg/modules/pr99377-2_b.C | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_a.C create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_b.C diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 9f18466192f..5af4d17ee3b 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -876,7 +876,7 @@ check_classfn (tree ctype, tree function, tree template_parms) void note_vague_linkage_fn (tree decl) { - if (processing_template_decl) + if (value_dependent_expression_p (decl)) return; DECL_DEFER_OUTPUT (decl) = 1; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 500ac06563a..79cbb346ffa 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -19074,6 +19074,8 @@ lazy_load_binding (unsigned mod, tree ns, tree id, binding_slot *mslot) timevar_start (TV_MODULE_IMPORT); + processing_template_decl_sentinel ptds; + /* Stop GC happening, even in outermost loads (because our caller could well be building up a lookup set). */ function_depth++; diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_a.C b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C new file mode 100644 index 00000000000..26e2bccbbbe --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C @@ -0,0 +1,5 @@ +// PR c++/99377 +// { dg-additional-options -fmodules-ts } +// { dg-module-cmi pr99377 } +export module pr99377; +export inline void f() { } diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_b.C b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C new file mode 100644 index 00000000000..69571952c8a --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C @@ -0,0 +1,6 @@ +// PR c++/99377 +// { dg-additional-options -fmodules-ts } +// { dg-do link } +import pr99377; +template<class> void g() { f(); } +int main() { g<int>(); } -- 2.38.0.rc2