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
trace_function(struct _Unwind_Context *,void * ntraced)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__))
call3_throw(size_t * ntraced)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__))
call3_nothrow(size_t * ntraced)34 void call3_nothrow(size_t* ntraced) {
35 _Unwind_Backtrace(trace_function, ntraced);
36 }
37
38 __attribute__ ((__noinline__, __disable_tail_calls__))
call2(size_t * ntraced,bool do_throw)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__))
call1(size_t * ntraced,bool do_throw)48 void call1(size_t* ntraced, bool do_throw) {
49 call2(ntraced, do_throw);
50 }
51
main()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