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* 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 void call3_throw(size_t* ntraced) {
25   try {
26     _Unwind_Backtrace(trace_function, ntraced);
27   } catch (...) {
28     assert(false);
29   }
30 }
31 
32 void call3_nothrow(size_t* ntraced) {
33   _Unwind_Backtrace(trace_function, ntraced);
34 }
35 
36 void call2(size_t* ntraced, bool do_throw) {
37   if (do_throw) {
38     call3_throw(ntraced);
39   } else {
40     call3_nothrow(ntraced);
41   }
42 }
43 
44 void call1(size_t* ntraced, bool do_throw) {
45   call2(ntraced, do_throw);
46 }
47 
48 int main() {
49   size_t throw_ntraced = 0;
50   size_t nothrow_ntraced = 0;
51 
52   call1(&nothrow_ntraced, false);
53 
54   try {
55     call1(&throw_ntraced, true);
56   } catch (...) {
57     assert(false);
58   }
59 
60   // Different platforms (and different runtimes) will unwind a different number
61   // of times, so we can't make any better assumptions than this.
62   assert(nothrow_ntraced > 1);
63   assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch
64   return 0;
65 }
66