Hi,
Currently, it seems that exception unwinding through a noexcept
function behaves basically as-if the noexcept function had try { code(); } catch (...) { std::terminate(); }
. As a result, std::terminate()
is called from a catch handler and unwinding is effectively considered done at that point, which means that we have lost the ability to extract information about where the exception was originated in the first place. For instance, we normally provide a stack trace of where the exception originated when an exception fails to be caught on macOS. However, when an exception propagates through a noexcept
function, we fail to provide a relevant stack trace. Instead it is as-if the exception had been caught and the program terminated, which means that we’ve lost the context of where the original exception had been thrown from. Another issue this creates is that these try-catch
create some amount of code bloat (I think this was raised a while back in Code generation for noexcept functions).
Can someone comment on whether it would make sense to instead implement this functionality by detecting that a frame is a noexcept function during unwinding, so that libunwind would effectively keep unwinding all the way up without trying to match catch
handlers. This would have the benefits that (1) we don’t need to generate calls to __clang_call_terminate
when calling a potentially-throwing function from a noexcept function, and (2) we’d process the throw + terminate-due-to-going-through-noexcept-frame as a single unwinding, which means that we’d keep the knowledge of where the exception was originated from.
Cheers,
Louis