[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 Jason Merrill changed: What|Removed |Added See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=97720 --- Comment #8 from Jason Merrill --- As discussed on PR97720, I think we could address this by changing noexcept regions to be represented as exception-specifications in the action table, and for C++17 and up using a different personality routine that knows that exception-specifications are noexcept.
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 m101010a at gmail dot com changed: What|Removed |Added CC||m101010a at gmail dot com --- Comment #7 from m101010a at gmail dot com --- I have written a GCC plugin (available at https://github.com/m42a/gcc-noexcept-plugin ) based on comment #6 that consistently prevents stack unwinding in this case.
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 --- Comment #6 from James Y Knight --- I realize that my suggestion above could only solve _most_ of the problem -- e.g. the original example, where the noexcept function doesn't have a try/catch in it. In that original example, there's no entry for the IP of the call in the LSDA table. The personality fn already knows during phase1 that this indicates termination -- but it simply fails to actually trigger the terminate in phase1, even though it easily could (& should!). However, in the example from comment #4, there _WILL_ be an entry in the callsite table covering the throw (necessarily, in order to to catch type "float"), so the "missing callsite => terminate" mechanism isn't applicable in that case. As the comment mentioned, to handle that, we'd need some alternative indication for termination which can be put in the action list. ISTM this could be done most straightforwardly by using an action record with a ttype pointing to a new ABI-defined special-purpose symbol (e.g. "__cxxabiv1::__eh_noexcept"). In libsupc++'s impl, that symbol can be an object whose type is a new std::type_info subclass, whose __do_catch overload calls terminate. Thus, when the personality fn falls through all the _actual_ catch action records, and comes to this, last one, it will query whether it can catch an exception by calling its __do_catch, and immediately trigger termination. GCC, then, can emit that as the last "catch" action in the chain for a try/catch in a noexcept function (instead of the cleanup action with code that calls std::terminate explicitly in the cleanup, that it does now).
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 James Y Knight changed: What|Removed |Added CC||foom at fuhm dot net --- Comment #5 from James Y Knight --- The originally-reported program still appears to exhibit the issue. Just looking at the unwind code -- and without attempting to test anything -- it appears that the solution may be as simple as inserting two lines: if (found_type == found_terminate) return _URC_FATAL_PHASE1_ERROR; at line 651 of eh_personality.cc (https://github.com/gcc-mirror/gcc/blob/b85a03ae11b157d60ddf93b71632efe0bde3bafd/libstdc%2B%2B-v3/libsupc%2B%2B/eh_personality.cc#L651) I believe that would abort the search phase (similarly to what happens if you run out of unwind frames before finding any catch handler) and cause _Unwind_RaiseException to return _URC_FATAL_PHASE1_ERROR, which then causes _cxa_throw to call terminate().
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 Sergey Barannikov changed: What|Removed |Added CC||barannikov88 at gmail dot com --- Comment #4 from Sergey Barannikov --- This is the ABI problem. The search phase of the unwinding process cannot distinguish between a case when a true handler found and a case when the search process should stop, because it has reached a call site that must not pass the exception through. In both cases _URC_HANDLER_FOUND is returned by the personality routine, and the second phase of the unwinding process begins (the actual unwinding). There is another problem in LSDA format (in action table format to be precise). Consider the following example: void bad_guy() noexcept { try { Foo foo; throw 0; } catch (float) { // Don't catch int. } } void level1() { bad_guy(); throw "dead code"; } int main() { try { level1(); } catch (const char *) { } } When you compile and run it you get: Foo::Foo() terminate called after throwing an instance of 'int' Aborted (core dumped) It works as expected. But (the funny thing) if you change "catch (const char *)" in main to "catch (int)", you will get this: Foo::Foo() Foo::~Foo() terminate called without an active exception Aborted (core dumped) This is because there is currently no way to represent a "Terminate" action in the action table of LSDA. gcc represents it as a simply cleanup action, that means that the unwinder does not stop at a noexcept function and continues searching for a handler up the stack. In the original example there is no handler for the exception thrown, and the runtime terminates the program instantly (no stack unwinding done). When one changes "catch (const char *)" to "catch (int)", the unwinder finds this handler at the search phase and launches the second, unwinding, phase. The unwinding process then destroys the local object "foo", checks the exception type for matching "float", and falls into the code that calls std::terminate when the matching fails. Since there is no __cxa_begin_catch prior to std::terminate, we get the error message "terminate called without an active exception" instead of correct "terminate called after throwing an instance of 'int'".
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 --- Comment #3 from Tobias Ringström 2013-01-09 17:39:20 UTC --- Yes, I want 'bad_guy' to be in the backtrace, so you are correct that I don't want the stack to be unwound at all, but unfortunately it is. It seems to be because of the Foo object somehow. If I remove the Foo object (or it's destructor), 'bad_guy' is in the backtrace.
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 --- Comment #2 from Jason Merrill 2013-01-09 14:42:54 UTC --- If you're looking for 'bad_guy' to be in the backtrace, that sounds to me like you want it to not be unwound at all, and I'm surprised that it doesn't already work that way.
[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55918 Jonathan Wakely changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2013-01-09 CC||jason at gcc dot gnu.org Ever Confirmed|0 |1 --- Comment #1 from Jonathan Wakely 2013-01-09 13:52:18 UTC --- I guess Jason can say whether this is a bug in the current behaviour or if your request should be severity=enhancement, but at the very least we need to document the intended behaviour at http://gcc.gnu.org/onlinedocs/gcc/Exception-handling.html