[all-commits] [llvm/llvm-project] c0a739: [ItaniumCXXABI] Add -fassume-nothrow-exception-dto...
Fangrui Song via All-commits
all-commits at lists.llvm.org
Sun Nov 5 00:39:54 PDT 2023
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: c0a73918bfddc6a04a897aab57fb95e8d2da7ec0
https://github.com/llvm/llvm-project/commit/c0a73918bfddc6a04a897aab57fb95e8d2da7ec0
Author: Fangrui Song <i at maskray.me>
Date: 2023-11-05 (Sun, 05 Nov 2023)
Changed paths:
M clang/docs/ReleaseNotes.rst
M clang/docs/UsersManual.rst
M clang/include/clang/Basic/DiagnosticSemaKinds.td
M clang/include/clang/Basic/LangOptions.def
M clang/include/clang/Driver/Options.td
M clang/lib/CodeGen/ItaniumCXXABI.cpp
M clang/lib/Driver/ToolChains/Clang.cpp
M clang/lib/Sema/SemaExprCXX.cpp
M clang/test/CodeGenCXX/eh.cpp
M clang/test/CodeGenCXX/exceptions.cpp
M clang/test/CodeGenCoroutines/coro-cleanup.cpp
M clang/test/Driver/clang-exception-flags.cpp
A clang/test/SemaCXX/assume-nothrow-exception-dtor.cpp
Log Message:
-----------
[ItaniumCXXABI] Add -fassume-nothrow-exception-dtor to assume that all exception objects' destructors are non-throwing
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
More information about the All-commits
mailing list