diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 64cf368e6e6849..917388f86811fe 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -327,6 +327,7 @@ {'is_defined': False, 'name': '___cxa_bad_cast', 'type': 'U'} {'is_defined': False, 'name': '___cxa_bad_typeid', 'type': 'U'} {'is_defined': False, 'name': '___cxa_begin_catch', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_call_terminate', 'type': 'U'} {'is_defined': False, 'name': '___cxa_call_unexpected', 'type': 'U'} {'is_defined': False, 'name': '___cxa_current_exception_type', 'type': 'U'} {'is_defined': False, 'name': '___cxa_current_primary_exception', 'type': 'U'} @@ -2593,6 +2594,7 @@ {'is_defined': True, 'name': '___cxa_bad_cast', 'type': 'I'} {'is_defined': True, 'name': '___cxa_bad_typeid', 'type': 'I'} {'is_defined': True, 'name': '___cxa_begin_catch', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_call_terminate', 'type': 'I'} {'is_defined': True, 'name': '___cxa_call_unexpected', 'type': 'I'} {'is_defined': True, 'name': '___cxa_current_exception_type', 'type': 'I'} {'is_defined': True, 'name': '___cxa_current_primary_exception', 'type': 'I'} diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 8751dffe230259..8af5db472f7c3a 100644 --- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -2301,6 +2301,7 @@ {'is_defined': True, 'name': '__cxa_bad_cast', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_bad_typeid', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_begin_catch', 'type': 'FUNC'} +{'is_defined': True, 'name': '__cxa_call_terminate', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_call_unexpected', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_current_exception_type', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_current_primary_exception', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index d578b41383c0e3..defe235a283c21 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -327,6 +327,7 @@ {'is_defined': False, 'name': '___cxa_bad_cast', 'type': 'U'} {'is_defined': False, 'name': '___cxa_bad_typeid', 'type': 'U'} {'is_defined': False, 'name': '___cxa_begin_catch', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_call_terminate', 'type': 'U'} {'is_defined': False, 'name': '___cxa_call_unexpected', 'type': 'U'} {'is_defined': False, 'name': '___cxa_current_exception_type', 'type': 'U'} {'is_defined': False, 'name': '___cxa_current_primary_exception', 'type': 'U'} @@ -2627,6 +2628,7 @@ {'is_defined': True, 'name': '___cxa_bad_cast', 'type': 'I'} {'is_defined': True, 'name': '___cxa_bad_typeid', 'type': 'I'} {'is_defined': True, 'name': '___cxa_begin_catch', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_call_terminate', 'type': 'I'} {'is_defined': True, 'name': '___cxa_call_unexpected', 'type': 'I'} {'is_defined': True, 'name': '___cxa_current_exception_type', 'type': 'I'} {'is_defined': True, 'name': '___cxa_current_primary_exception', 'type': 'I'} diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index fc0f4fcf415e63..6b77cda1e2866d 100644 --- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -2295,6 +2295,7 @@ {'is_defined': True, 'name': '__cxa_bad_cast', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_bad_typeid', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_begin_catch', 'type': 'FUNC'} +{'is_defined': True, 'name': '__cxa_call_terminate', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_call_unexpected', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_current_exception_type', 'type': 'FUNC'} {'is_defined': True, 'name': '__cxa_current_primary_exception', 'type': 'FUNC'} diff --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h index 0e3969084e04fd..8d1b5c9b55782a 100644 --- a/libcxxabi/include/cxxabi.h +++ b/libcxxabi/include/cxxabi.h @@ -77,6 +77,11 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup(); #endif extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type(); +// GNU extension +// Calls `terminate` with the current exception being caught. This function is used by GCC when a `noexcept` function +// throws an exception inside a try/catch block and doesn't catch it. +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_call_terminate(void*) throw(); + // 2.5.4 Rethrowing Exceptions extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow(); diff --git a/libcxxabi/lib/itanium-exceptions.exp b/libcxxabi/lib/itanium-exceptions.exp index 21b19edb92dfc4..9a7f317b0232e8 100644 --- a/libcxxabi/lib/itanium-exceptions.exp +++ b/libcxxabi/lib/itanium-exceptions.exp @@ -5,6 +5,7 @@ ___cxa_begin_catch ___cxa_call_unexpected ___cxa_current_exception_type ___cxa_end_catch +___cxa_call_terminate ___cxa_free_dependent_exception ___cxa_free_exception ___cxa_get_exception_ptr diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index ff69a4c65e465e..92901a83bfd039 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -589,6 +589,11 @@ void __cxa_end_catch() { } } +void __cxa_call_terminate(void* unwind_arg) throw() { + __cxa_begin_catch(unwind_arg); + std::terminate(); +} + // Note: exception_header may be masquerading as a __cxa_dependent_exception // and that's ok. exceptionType is there too. // However watch out for foreign exceptions. Return null for them. diff --git a/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp b/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp index a0d1f36f050f05..a66e6c9e530756 100644 --- a/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp +++ b/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp @@ -8,16 +8,11 @@ // UNSUPPORTED: no-exceptions -#include - -// Clang emits warnings about exceptions of type 'Child' being caught by -// an earlier handler of type 'Base'. Congrats clang, you've just -// diagnosed the behavior under test. -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wexceptions" -#endif +// Clang and GCC emit warnings about exceptions of type 'Child' being caught by +// an earlier handler of type 'Base'. +// ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions -#if __has_feature(cxx_nullptr) +#include struct A {}; @@ -124,18 +119,6 @@ void test6() } } - -#else - -void test1() {} -void test2() {} -void test3() {} -void test4() {} -void test5() {} -void test6() {} - -#endif - int main(int, char**) { test1(); test2(); diff --git a/libcxxabi/test/cxa_call_terminate.pass.cpp b/libcxxabi/test/cxa_call_terminate.pass.cpp new file mode 100644 index 00000000000000..d0c5d13197ff0f --- /dev/null +++ b/libcxxabi/test/cxa_call_terminate.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-exceptions + +// We're testing the diagnosed behaviour here. +// ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions + +#include +#include +#include + +#include "test_macros.h" + +void func() TEST_NOEXCEPT { + try { + throw 1; + } catch (float) { + } +} + +void terminate_handler() { + assert(std::current_exception() != nullptr); + std::exit(0); +} + +int main(int, char**) { + std::set_terminate(terminate_handler); + func(); + assert(false); +}