xref: /aosp_15_r20/external/libcxxabi/test/backtrace_test.pass.cpp (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
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(&nothrow_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