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:" } }