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.

Reply via email to