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;

Reply via email to