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

Reply via email to