LLVM/Clangでは「C++例外オブジェクトのデストラクタで例外送出しないと仮定する」コンパイルオプション-fassume-nothrow-exception-dtorが提供される。こんな邪悪な例外クラスを扱うユースケースは無いだろうが、C++言語仕様上は禁止されていない。
// デストラクタで例外送出する例外オブジェクト struct evil_exception { ~evil_exception() noexcept(false) { throw 42; } }; void func() { try { throw evil_exception{}; } catch (...) { std::puts("1st catch"); } } int main() { try { func(); } catch (...) { std::puts("2nd catch"); } }
Clangに-fassume-nothrow-exception-dtorオプション指定すると、上記evil_exceptionデストラクタはコンパイルエラーとして拒絶する。
error: cannot throw object of type 'evil_exception' with a potentially-throwing destructor
Clang 18で導入されたコンパイルオプション。
New Compiler Flags
Clang 18.1.1 Release Notes — Clang 18.1.1 documentation
-fassume-nothrow-exception-dtoris added to assume that the destructor of a thrown exception object will not throw. The generated code for catch handlers will be smaller. A throw expression of a type with a potentially-throwing destructor will lead to an error.
-fassume-nothrow-exception-dtor
Assume that an exception object' destructor will not throw, and generate less code for catch handlers. A throw expression of a type with a potentially-throwing destructor will lead to an error.By default, Clang assumes that the exception object may have a throwing destructor. For the Itanium C++ ABI, Clang generates a landing pad to destroy local variables and call
Clang Compiler User’s Manual — Clang 18.1.1 documentation_Unwind_Resumefor the codecatch (...) { ... }. This option tells Clang that an exception object’s destructor will not throw and code simplification is possible.
おまけ
C++処理系毎に実行結果が異なる模様。いずれにせよ実用性は皆無。
GCC, Clang/libstdc++の実行結果:
1st catch
2nd catch
Clang/libc++の実行結果:
libc++abi: terminating due to uncaught exception of type int
Program terminated with signal: SIGSEGV
MSVC v19.50の実行結果:std::terminate呼び出し結果に相当する例外コード0xc0000409 STATUS_STACK_BUFFER_OVERRUNでプロセス異常終了する。*1
関連URL: