https://gcc.gnu.org/g:870e66a3fcbde185c086f10e63ac1c9fe946e233

commit r16-754-g870e66a3fcbde185c086f10e63ac1c9fe946e233
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Mon May 19 22:11:13 2025 +1000

    c++/modules: Ensure vtables are emitted when needed [PR120349]
    
    I missed a testcase in r16-688-gc875748cdc468e for whether a GM vtable
    should be emitted in an importer when it has no non-inline key function.
    Before that patch the code worked because always we marked all vtables
    as DECL_EXTERNAL, which then meant that reading the definition marked
    them as DECL_NOT_REALLY_EXTERN.
    
    This patch restores the old behaviour so that vtables are marked
    DECL_EXTERNAL (and hence DECL_NOT_REALLY_EXTERN).
    
            PR c++/120349
    
    gcc/cp/ChangeLog:
    
            * module.cc (trees_out::core_bools): Always mark vtables as
            DECL_EXTERNAL.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/vtt-3_a.C: New test.
            * g++.dg/modules/vtt-3_b.C: New test.
    
    Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/module.cc                       |  8 ++++++--
 gcc/testsuite/g++.dg/modules/vtt-3_a.C | 29 +++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/vtt-3_b.C | 14 ++++++++++++++
 3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index f728275612eb..13f8770b7bd1 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -5724,9 +5724,13 @@ trees_out::core_bools (tree t, bits_out& bits)
           DECL_NOT_REALLY_EXTERN -> base.not_really_extern
             == that was a lie, it is here  */
 
-       /* decl_flag_1 is DECL_EXTERNAL. Things we emit here, might
-          well be external from the POV of an importer.  */
        bool is_external = t->decl_common.decl_flag_1;
+       /* maybe_emit_vtables relies on vtables being marked as
+          DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN before processing.  */
+       if (!is_external && VAR_P (t) && DECL_VTABLE_OR_VTT_P (t))
+         is_external = true;
+       /* Things we emit here might well be external from the POV of an
+          importer.  */
        if (!is_external
            && VAR_OR_FUNCTION_DECL_P (t)
            && get_importer_interface (t) == importer_interface::external)
diff --git a/gcc/testsuite/g++.dg/modules/vtt-3_a.C 
b/gcc/testsuite/g++.dg/modules/vtt-3_a.C
new file mode 100644
index 000000000000..f38f024ba1ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-3_a.C
@@ -0,0 +1,29 @@
+// PR c++/120349
+// { dg-additional-options "-fmodules -Wno-global-module" }
+// { dg-module-cmi M }
+
+module;
+
+// GMF types; should have vtables emitted in importers
+struct BGG {
+  virtual inline ~BGG() {}
+};
+struct BGM {
+  virtual inline ~BGM() {}
+};
+struct DGG : BGG {};
+
+export module M;
+
+export using ::DGG;
+
+// Module-local types; should have vtables emitted here
+struct BM {
+  virtual inline ~BM() {}
+};
+export struct DGM : BGM {};  // note: this emits BGM's vtable here too
+export struct DM : BM {};
+
+// { dg-final { scan-assembler-not "_ZTV3BGG:" } }
+// { dg-final { scan-assembler "_ZTV3BGM:" } }
+// { dg-final { scan-assembler "_ZTVW1M2BM:" } }
diff --git a/gcc/testsuite/g++.dg/modules/vtt-3_b.C 
b/gcc/testsuite/g++.dg/modules/vtt-3_b.C
new file mode 100644
index 000000000000..ef7ae6ca4e6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-3_b.C
@@ -0,0 +1,14 @@
+// PR c++/120349
+// { dg-additional-options "-fmodules -Wno-global-module" }
+
+import M;
+
+int main() {
+  DGG dgg;
+  DGM dgm;
+  DM dm;
+}
+
+// { dg-final { scan-assembler "_ZTV3BGG:" } }
+// { dg-final { scan-assembler "_ZTV3BGM:" } }
+// { dg-final { scan-assembler-not "_ZTVW1M2BM:" } }

Reply via email to