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#include <assert.h>
10#include <unwind.h>
11
12extern "C" _Unwind_Reason_Code
13trace_function(struct _Unwind_Context* context, void* ntraced) {
14  (*reinterpret_cast<size_t*>(ntraced))++;
15  // We should never have a call stack this deep...
16  assert(*reinterpret_cast<size_t*>(ntraced) < 20);
17  return _URC_NO_REASON;
18}
19
20void call3_throw(size_t* ntraced) {
21  try {
22    _Unwind_Backtrace(trace_function, ntraced);
23  } catch (...) {
24    assert(false);
25  }
26}
27
28void call3_nothrow(size_t* ntraced) {
29  _Unwind_Backtrace(trace_function, ntraced);
30}
31
32void call2(size_t* ntraced, bool do_throw) {
33  if (do_throw) {
34    call3_throw(ntraced);
35  } else {
36    call3_nothrow(ntraced);
37  }
38}
39
40void call1(size_t* ntraced, bool do_throw) {
41  call2(ntraced, do_throw);
42}
43
44int main() {
45  size_t throw_ntraced = 0;
46  size_t nothrow_ntraced = 0;
47
48  call1(&nothrow_ntraced, false);
49
50  try {
51    call1(&throw_ntraced, true);
52  } catch (...) {
53    assert(false);
54  }
55
56  // Different platforms (and different runtimes) will unwind a different number
57  // of times, so we can't make any better assumptions than this.
58  assert(nothrow_ntraced > 1);
59  assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch
60  return 0;
61}
62