[libc++abi] Fix test failures with GCC 14 (#95759)

This adds a new `__cxa_call_terminate`, which GCC 14 generates calls to
now. Clang had `__clang_call_terminate` for the same use-case for a long
time. It also fixes a test that is enabled now, since GCC has the
`__has_feature` FTM now.
This commit is contained in:
Nikolas Klauser 2024-06-30 12:09:20 +02:00 committed by GitHub
parent 22dfa1aa2c
commit 0c9f537d41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 57 additions and 21 deletions

View File

@ -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'}

View File

@ -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'}

View File

@ -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'}

View File

@ -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'}

View File

@ -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();

View File

@ -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

View File

@ -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.

View File

@ -8,17 +8,12 @@
// UNSUPPORTED: no-exceptions
// Clang and GCC emit warnings about exceptions of type 'Child' being caught by
// an earlier handler of type 'Base'.
// ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions
#include <cassert>
// 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
#if __has_feature(cxx_nullptr)
struct A {};
void test1()
@ -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();

View File

@ -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 <cassert>
#include <cstdlib>
#include <exception>
#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);
}