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 also check DECL_VIRTUAL_P in addition to 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. gcc/testsuite/ChangeLog: * g++.target/aarch64/virtual-lto.C: New test. --- 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/riscv/riscv.cc | 2 +- gcc/config/rs6000/rs6000.cc | 2 +- gcc/testsuite/g++.target/aarch64/virtual-lto.C | 16 ++++++++++++++++ 5 files changed, 20 insertions(+), 4 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 031da863860..2e04c32b51c 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -21120,7 +21120,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) || DECL_VINDEX (versn->decl)) sorry ("virtual function multiversioning not supported"); fn_ver_vec.safe_push (versn->decl); diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index c313fb85f9b..705407114f0 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -5559,7 +5559,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) || DECL_VINDEX (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 41ee4014c0d..bc2e9738242 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -14613,7 +14613,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) || DECL_VINDEX (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 1049c446c40..1a30f9ad835 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -25646,7 +25646,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) || DECL_VINDEX (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
