aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSimon Rainer <gcc.gnu@vvalter.com>2022-08-31 23:00:08 +0200
committerRichard Biener <rguenther@suse.de>2022-09-02 08:06:14 +0200
commit0b0a3cdbff64d97e7de3e0e2c26e965708064193 (patch)
treed285ecf1c0f7d1242fa58571fa94f0cc03796d7d /gcc
parentbb0a1556df79d02cf570f5eb17a1b02a509f0be4 (diff)
downloadgcc-0b0a3cdbff64d97e7de3e0e2c26e965708064193.zip
gcc-0b0a3cdbff64d97e7de3e0e2c26e965708064193.tar.gz
gcc-0b0a3cdbff64d97e7de3e0e2c26e965708064193.tar.bz2
ipa: Fix throw in multi-versioned functions [PR106627]
Any multi-versioned function was implicitly declared as noexcept, which leads to an abort if an exception is thrown inside the function. The reason for this is that the function declaration is replaced by a newly created dispatcher declaration, which has TREE_NOTHROW always set to 1. Instead we need to set TREE_NOTHROW to the value of the original declaration. PR ipa/106627 gcc/ChangeLog: * config/i386/i386-features.cc (ix86_get_function_versions_dispatcher): Set TREE_NOTHROW correctly for dispatcher declaration. * config/rs6000/rs6000.cc (rs6000_get_function_versions_dispatcher): Likewise. gcc/testsuite/ChangeLog: * g++.target/i386/pr106627.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386-features.cc1
-rw-r--r--gcc/config/rs6000/rs6000.cc1
-rw-r--r--gcc/testsuite/g++.target/i386/pr106627.C28
3 files changed, 30 insertions, 0 deletions
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index d6bb66c..fd212262 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -3268,6 +3268,7 @@ ix86_get_function_versions_dispatcher (void *decl)
/* Right now, the dispatching is done via ifunc. */
dispatch_decl = make_dispatcher_decl (default_node->decl);
+ TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn);
dispatcher_node = cgraph_node::get_create (dispatch_decl);
gcc_assert (dispatcher_node != NULL);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 2f3146e..937954b 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -24861,6 +24861,7 @@ rs6000_get_function_versions_dispatcher (void *decl)
/* Right now, the dispatching is done via ifunc. */
dispatch_decl = make_dispatcher_decl (default_node->decl);
+ TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn);
dispatcher_node = cgraph_node::get_create (dispatch_decl);
gcc_assert (dispatcher_node != NULL);
diff --git a/gcc/testsuite/g++.target/i386/pr106627.C b/gcc/testsuite/g++.target/i386/pr106627.C
new file mode 100644
index 0000000..e993d82
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr106627.C
@@ -0,0 +1,28 @@
+/* PR c++/103012 Exception handling with multiversioned functions */
+/* { dg-do run } */
+/* { dg-require-ifunc "" } */
+
+extern "C" void abort (void);
+
+__attribute__((target("default")))
+void f() {
+ throw 1;
+}
+
+__attribute__((target("sse4.2,bmi")))
+void f() {
+ throw 2;
+}
+
+int main()
+{
+ try {
+ f();
+ }
+ catch(...)
+ {
+ return 0;
+ }
+
+ abort ();
+}