When building with LTO, DECL_VINDEX is not always set for virtual functions, which allows virtual functions to be incorrectly treated as non-virtual and then being multi-versioned, and causes errors sometimes.
This patch addresses the issue by ensuring that we check DECL_VIRTUAL_P instead of DECL_VINDEX when handling virtual functions during multiversioning. Signed-off-by: Yangyu Chen <[email protected]> gcc/ChangeLog: * config/aarch64/aarch64.cc (aarch64_generate_version_dispatcher_body): Check DECL_VIRTUAL_P for virtual functions for LTO handling. * config/i386/i386-features.cc (ix86_generate_version_dispatcher_body): Ditto. * config/riscv/riscv.cc (riscv_generate_version_dispatcher_body): Ditto. * config/rs6000/rs6000.cc (rs6000_generate_version_dispatcher_body): Ditto. * config/loongarch/loongarch.cc (loongarch_generate_version_dispatcher_body): Ditto. gcc/testsuite/ChangeLog: * g++.target/aarch64/virtual-lto.C: New test. --- Changes since v3: - Apply to loongarch. - Only checks DECL_VIRTUAL_P v3: https://patchwork.sourceware.org/project/gcc/patch/[email protected]/ Changes since v2: - Rebase with latest master. v2: https://patchwork.sourceware.org/project/gcc/patch/[email protected]/ Changes since v1: - Add testcase v1: https://patchwork.sourceware.org/project/gcc/patch/[email protected]/ --- gcc/config/aarch64/aarch64.cc | 2 +- gcc/config/i386/i386-features.cc | 2 +- gcc/config/loongarch/loongarch.cc | 2 +- gcc/config/riscv/riscv.cc | 2 +- gcc/config/rs6000/rs6000.cc | 2 +- gcc/testsuite/g++.target/aarch64/virtual-lto.C | 16 ++++++++++++++++ 6 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.target/aarch64/virtual-lto.C diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 00e619f26c5..2d7423cf275 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -21708,7 +21708,7 @@ aarch64_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (versn->decl)) + if (DECL_VIRTUAL_P (versn->decl)) sorry ("virtual function multiversioning not supported"); if (dump_enabled_p ()) diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index d5435f009cb..6eb6a69902c 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -5703,7 +5703,7 @@ ix86_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (versn->decl)) + if (DECL_VIRTUAL_P (versn->decl)) sorry ("virtual function multiversioning not supported"); fn_ver_vec.safe_push (versn->decl); diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 2c13a86176d..e5d67c8e171 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -12053,7 +12053,7 @@ loongarch_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (versn->decl)) + if (DECL_VIRTUAL_P (versn->decl)) sorry ("virtual function multiversioning not supported"); fn_ver_vec.safe_push (versn->decl); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3baf0a936b5..c00391d8bdd 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -15530,7 +15530,7 @@ riscv_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (versn->decl)) + if (DECL_VIRTUAL_P (versn->decl)) sorry ("virtual function multiversioning not supported"); fn_ver_vec.safe_push (versn->decl); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index a4f60ecb58a..3838059a7e2 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -25645,7 +25645,7 @@ rs6000_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (version->decl)) + if (DECL_VIRTUAL_P (version->decl)) sorry ("Virtual function multiversioning not supported"); fn_ver_vec.safe_push (version->decl); diff --git a/gcc/testsuite/g++.target/aarch64/virtual-lto.C b/gcc/testsuite/g++.target/aarch64/virtual-lto.C new file mode 100644 index 00000000000..41ebdcd006d --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/virtual-lto.C @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-additional-options "-flto" } */ +class foo { +public: + virtual void bar () = 0; +}; + +class baz : public foo { +public: + void bar (); +}; + +__attribute__((target_clones("default", "flagm"))) +void baz::bar () { +} /* { dg-message "sorry, unimplemented: virtual function multiversioning not supported" } */ -- 2.51.0
