https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97720
Jason Merrill <jason at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Last reconfirmed| |2023-05-22 Summary|Sometimes |throw in try in noexcept fn |std::current_exception does |calls terminate without |not work properly in the |handling the exception |terminate handler | Status|UNCONFIRMED |NEW CC| |jason at gcc dot gnu.org --- Comment #4 from Jason Merrill <jason at gcc dot gnu.org> --- Yes. https://eel.is/c++draft/except#handle-7 : "Also, an implicit handler is considered active when the function std::terminate is entered due to a throw." This is handled properly for the case where there is no possible catch clause between the call and the noexcept: in that case the call site has no EH landing pad, so the personality function calls __cxa_call_terminate, which properly handles the exception. In the comment #3 case where there are catch clauses, we represent the noexcept region around the catch as a cleanup. This also means that the phase 1 search for a handler looks past it rather than properly recognizing that we found a (terminating) handler. And we call std::terminate directly rather than through __cxa_call_terminate, so indeed std::current_exception is wrong. I assume the optimization sensitivity the original testcase is seeing is due to inlining changing whether a particular call falls into the first or second case above. It looks like Clang represents the second case roughly as catch (...) { std::terminate(); } It seems to me that it would be superior to represent the second case in the action table as an empty exception specification like C++98 throw(), but in the generated code hand off to __cxa_call_terminate rather than __cxa_call_unexpected. Representing it that way rather than catch(...) would work better for PR88218 and PR55918.