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