| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | #include <assert.h> |
| | #include <stddef.h> |
| | #include <unwind.h> |
| |
|
| | extern "C" _Unwind_Reason_Code |
| | trace_function(struct _Unwind_Context*, void* ntraced) { |
| | (*reinterpret_cast<size_t*>(ntraced))++; |
| | |
| | assert(*reinterpret_cast<size_t*>(ntraced) < 20); |
| | return _URC_NO_REASON; |
| | } |
| |
|
| | __attribute__ ((__noinline__)) |
| | void call3_throw(size_t* ntraced) { |
| | try { |
| | _Unwind_Backtrace(trace_function, ntraced); |
| | } catch (...) { |
| | assert(false); |
| | } |
| | } |
| |
|
| | __attribute__ ((__noinline__, __disable_tail_calls__)) |
| | void call3_nothrow(size_t* ntraced) { |
| | _Unwind_Backtrace(trace_function, ntraced); |
| | } |
| |
|
| | __attribute__ ((__noinline__, __disable_tail_calls__)) |
| | void call2(size_t* ntraced, bool do_throw) { |
| | if (do_throw) { |
| | call3_throw(ntraced); |
| | } else { |
| | call3_nothrow(ntraced); |
| | } |
| | } |
| |
|
| | __attribute__ ((__noinline__, __disable_tail_calls__)) |
| | void call1(size_t* ntraced, bool do_throw) { |
| | call2(ntraced, do_throw); |
| | } |
| |
|
| | int main() { |
| | size_t throw_ntraced = 0; |
| | size_t nothrow_ntraced = 0; |
| |
|
| | call1(¬hrow_ntraced, false); |
| |
|
| | try { |
| | call1(&throw_ntraced, true); |
| | } catch (...) { |
| | assert(false); |
| | } |
| |
|
| | |
| | |
| | assert(nothrow_ntraced > 1); |
| | assert(throw_ntraced == nothrow_ntraced); |
| | return 0; |
| | } |
| |
|