Home | History | Annotate | Download | only in test
      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(&nothrow_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