
Link: https://lists.llvm.org/pipermail/cfe-dev/2021-August/068740.html ("[Exception Handling] Could we mark __cxa_end_catch as nounwind conditionally?" Link: https://github.com/llvm/llvm-project/issues/57375 A catch handler calls `__cxa_begin_catch` and `__cxa_end_catch`. For a catch-all clause or a catch clause matching a record type, we: * assume that the exception object may have a throwing destructor * emit `invoke void @__cxa_end_catch` (as the call is not marked as the `nounwind` attribute). * emit a landing pad to destroy local variables and call `_Unwind_Resume` ``` struct A { ~A(); }; struct B { int x; }; void opaque(); void foo() { A a; try { opaque(); } catch (...) { } // the exception object has an unknown type and may throw try { opaque(); } catch (B b) { } // B::~B is nothrow, but we do not utilize this } ``` Per C++ [dcl.fct.def.coroutine], a coroutine's function body implies a `catch (...)`. Our code generation pessimizes even simple code, like: ``` UserFacing foo() { A a; opaque(); co_return; // For `invoke void @__cxa_end_catch()`, the landing pad destroys the // promise_type and deletes the coro frame. } ``` Throwing destructors are typically discouraged. In many environments, the destructors of exception objects are guaranteed to never throw, making our conservative code generation approach seem wasteful. Furthermore, throwing destructors tend not to work well in practice: * GCC does not emit call site records for the region containing `__cxa_end_catch`. This has been a long time, since 2000. * If a catch-all clause catches an exception object that throws, both GCC and Clang using libstdc++ leak the allocated exception object. To avoid code generation pessimization, add an opt-in driver option -fassume-nothrow-exception-dtor to assume that `__cxa_end_catch` calls have the `nounwind` attribute. This implies that thrown exception objects' destructors will never throw. To detect misuses, diagnose throw expressions with a potentially-throwing destructor. Technically, it is possible that a potentially-throwing destructor never throws when called transitively by `__cxa_end_catch`, but these cases seem rare enough to justify a relaxed mode. Reviewed By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D108905
33 lines
1.7 KiB
C++
33 lines
1.7 KiB
C++
// We force the target to unknown because clang's default behavior for
|
|
// exception handling is target dependent.
|
|
// RUN: %clang -### -target unknown %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
|
|
// DEFAULT: "-cc1" {{.*}} "-fcxx-exceptions" "-fexceptions"
|
|
//
|
|
// RUN: %clang -### -fexceptions %s 2>&1 | FileCheck %s -check-prefix=ON1
|
|
// ON1: "-cc1" {{.*}} "-fcxx-exceptions" "-fexceptions"
|
|
//
|
|
// RUN: %clang -### -fno-exceptions -fcxx-exceptions %s 2>&1 | FileCheck %s -check-prefix=ON2
|
|
// ON2: "-cc1" {{.*}} "-fcxx-exceptions" "-fexceptions"
|
|
//
|
|
// RUN: %clang -### -fno-cxx-exceptions -fexceptions %s 2>&1 | FileCheck %s -check-prefix=ON3
|
|
// ON3: "-cc1" {{.*}} "-fcxx-exceptions" "-fexceptions"
|
|
//
|
|
// RUN: %clang -### -fno-exceptions %s 2>&1 | FileCheck %s -check-prefix=OFF1
|
|
// OFF1-NOT: "-cc1" {{.*}} "-fcxx-exceptions"
|
|
//
|
|
// RUN: %clang -### -fno-cxx-exceptions %s 2>&1 | FileCheck %s -check-prefix=OFF2
|
|
// OFF2-NOT: "-cc1" {{.*}} "-fcxx-exceptions"
|
|
//
|
|
// RUN: %clang -### -fcxx-exceptions -fno-exceptions %s 2>&1 | FileCheck %s -check-prefix=OFF3
|
|
// OFF3-NOT: "-cc1" {{.*}} "-fcxx-exceptions"
|
|
//
|
|
// RUN: %clang -### -fexceptions -fno-cxx-exceptions %s 2>&1 | FileCheck %s -check-prefix=OFF4
|
|
// OFF4-NOT: "-cc1" {{.*}} "-fcxx-exceptions"
|
|
//
|
|
// RUN: %clang -### -target x86_64-scei-ps4 %s 2>&1 | FileCheck %s -check-prefix=PS-OFF
|
|
// RUN: %clang -### -target x86_64-sie-ps5 %s 2>&1 | FileCheck %s -check-prefix=PS-OFF
|
|
// PS-OFF-NOT: "-cc1" {{.*}} "-f{{(cxx-)?}}exceptions"
|
|
|
|
// RUN: %clang -### -fexceptions -fno-assume-nothrow-exception-dtor -fassume-nothrow-exception-dtor %s 2>&1 | FileCheck %s --check-prefix=NOTHROW-DTOR
|
|
// NOTHROW-DTOR: "-cc1"{{.*}} "-fcxx-exceptions" "-fassume-nothrow-exception-dtor"
|