1 //===---------------------- backtrace_test.cpp ----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: libcxxabi-no-exceptions 11 12 #include <assert.h> 13 #include <stddef.h> 14 #include <unwind.h> 15 16 extern "C" _Unwind_Reason_Code 17 trace_function(struct _Unwind_Context*, void* ntraced) { 18 (*reinterpret_cast<size_t*>(ntraced))++; 19 // We should never have a call stack this deep... 20 assert(*reinterpret_cast<size_t*>(ntraced) < 20); 21 return _URC_NO_REASON; 22 } 23 24 __attribute__ ((__noinline__)) 25 void call3_throw(size_t* ntraced) { 26 try { 27 _Unwind_Backtrace(trace_function, ntraced); 28 } catch (...) { 29 assert(false); 30 } 31 } 32 33 __attribute__ ((__noinline__, __disable_tail_calls__)) 34 void call3_nothrow(size_t* ntraced) { 35 _Unwind_Backtrace(trace_function, ntraced); 36 } 37 38 __attribute__ ((__noinline__, __disable_tail_calls__)) 39 void call2(size_t* ntraced, bool do_throw) { 40 if (do_throw) { 41 call3_throw(ntraced); 42 } else { 43 call3_nothrow(ntraced); 44 } 45 } 46 47 __attribute__ ((__noinline__, __disable_tail_calls__)) 48 void call1(size_t* ntraced, bool do_throw) { 49 call2(ntraced, do_throw); 50 } 51 52 int main() { 53 size_t throw_ntraced = 0; 54 size_t nothrow_ntraced = 0; 55 56 call1(¬hrow_ntraced, false); 57 58 try { 59 call1(&throw_ntraced, true); 60 } catch (...) { 61 assert(false); 62 } 63 64 // Different platforms (and different runtimes) will unwind a different number 65 // of times, so we can't make any better assumptions than this. 66 assert(nothrow_ntraced > 1); 67 assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch 68 return 0; 69 } 70