From: Simon Rainer Date: Wed, 31 Aug 2022 21:00:08 +0000 (+0200) Subject: ipa: Fix throw in multi-versioned functions [PR106627] X-Git-Tag: basepoints/gcc-14~4847 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b0a3cdbff64d97e7de3e0e2c26e965708064193;p=thirdparty%2Fgcc.git 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. --- diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index d6bb66cbe018..fd212262f503 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 2f3146e56f87..937954b6351c 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 000000000000..e993d825f20c --- /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 (); +}