https://gcc.gnu.org/g:acfe19f03bccd1f3183fd5d70d7a3c8c85e62fac
commit r15-9187-gacfe19f03bccd1f3183fd5d70d7a3c8c85e62fac Author: Jason Merrill <ja...@redhat.com> Date: Tue Apr 1 19:22:18 2025 -0400 c++/modules: inline loaded at eof std/format/string.cc and a few other libstdc++ tests were failing with module std with undefined references to __failed_to_parse_format_spec. This turned out to be because since r15-8012 we don't end up calling note_vague_linkage_fn for functions loaded after at_eof is set. But once import_export_decl decides on COMDAT linkage, we should be able to just clear DECL_EXTERNAL and let cgraph take it from there. I initially made this change in import_export_decl, but decided that for GCC 15 it would be safer to limit the change to modules. For GCC 16 I'd like to do away with DECL_NOT_REALLY_EXTERN entirely, it's been obsolete since cgraphunit in 2003. gcc/cp/ChangeLog: * module.cc (module_state::read_cluster) (post_load_processing): Clear DECL_EXTERNAL if DECL_COMDAT. Diff: --- gcc/cp/module.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index ce22b2ece3f0..89deabbfee37 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -16679,6 +16679,15 @@ module_state::read_cluster (unsigned snum) #endif cfun->returns_struct = aggr; expand_or_defer_fn (decl); + + /* If we first see this function after at_eof, it doesn't get + note_vague_linkage_fn from tentative_decl_linkage, so the loop in + c_parse_final_cleanups won't consider it. But with DECL_COMDAT we + can just clear DECL_EXTERNAL and let cgraph decide. + FIXME handle this outside module.cc after GCC 15. */ + if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl) + && DECL_NOT_REALLY_EXTERN (decl)) + DECL_EXTERNAL (decl) = false; } } @@ -19159,6 +19168,10 @@ post_load_processing () gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl)); expand_or_defer_fn (decl); + /* As in module_state::read_cluster. */ + if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl) + && DECL_NOT_REALLY_EXTERN (decl)) + DECL_EXTERNAL (decl) = false; } cfun = old_cfun;