[Bug c++/55918] Stack partially unwound when noexcept causes call to std::terminate

2023-08-11 Thread jason at gcc dot gnu.org via Gcc-bugs
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

2022-12-16 Thread m101010a at gmail dot com via Gcc-bugs
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

2021-12-04 Thread foom at fuhm dot net via Gcc-bugs
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

2021-11-14 Thread foom at fuhm dot net via Gcc-bugs
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

2016-10-19 Thread barannikov88 at gmail dot com
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

2013-01-09 Thread tobias at ringis dot se

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

2013-01-09 Thread jason at gcc dot gnu.org


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

2013-01-09 Thread redi at gcc dot gnu.org


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