/ test / backtrace_test.pass.cpp
backtrace_test.pass.cpp
 1  //===---------------------- backtrace_test.cpp ----------------------------===//
 2  //
 3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 4  // See https://llvm.org/LICENSE.txt for license information.
 5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 6  //
 7  //===----------------------------------------------------------------------===//
 8  
 9  // UNSUPPORTED: no-exceptions
10  
11  #include <assert.h>
12  #include <stddef.h>
13  #include <unwind.h>
14  
15  extern "C" _Unwind_Reason_Code
16  trace_function(struct _Unwind_Context*, void* ntraced) {
17    (*reinterpret_cast<size_t*>(ntraced))++;
18    // We should never have a call stack this deep...
19    assert(*reinterpret_cast<size_t*>(ntraced) < 20);
20    return _URC_NO_REASON;
21  }
22  
23  __attribute__ ((__noinline__))
24  void call3_throw(size_t* ntraced) {
25    try {
26      _Unwind_Backtrace(trace_function, ntraced);
27    } catch (...) {
28      assert(false);
29    }
30  }
31  
32  __attribute__ ((__noinline__, __disable_tail_calls__))
33  void call3_nothrow(size_t* ntraced) {
34    _Unwind_Backtrace(trace_function, ntraced);
35  }
36  
37  __attribute__ ((__noinline__, __disable_tail_calls__))
38  void call2(size_t* ntraced, bool do_throw) {
39    if (do_throw) {
40      call3_throw(ntraced);
41    } else {
42      call3_nothrow(ntraced);
43    }
44  }
45  
46  __attribute__ ((__noinline__, __disable_tail_calls__))
47  void call1(size_t* ntraced, bool do_throw) {
48    call2(ntraced, do_throw);
49  }
50  
51  int main(int, char**) {
52    size_t throw_ntraced = 0;
53    size_t nothrow_ntraced = 0;
54  
55    call1(&nothrow_ntraced, false);
56  
57    try {
58      call1(&throw_ntraced, true);
59    } catch (...) {
60      assert(false);
61    }
62  
63    // Different platforms (and different runtimes) will unwind a different number
64    // of times, so we can't make any better assumptions than this.
65    assert(nothrow_ntraced > 1);
66    assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch
67    return 0;
68  }