1605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//===---------------------- backtrace_test.cpp ----------------------------===//
2605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//
3605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//                     The LLVM Compiler Infrastructure
4605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//
5605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
6605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert// Source Licenses. See LICENSE.TXT for details.
7605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//
8605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert//===----------------------------------------------------------------------===//
9605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert#include <assert.h>
10605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert#include <unwind.h>
11605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
12605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertextern "C" _Unwind_Reason_Code
13605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Alberttrace_function(struct _Unwind_Context* context, void* ntraced) {
14605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  (*reinterpret_cast<size_t*>(ntraced))++;
15605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  // We should never have a call stack this deep...
16605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  assert(*reinterpret_cast<size_t*>(ntraced) < 20);
17605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  return _URC_NO_REASON;
18605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
19605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
20605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertvoid call3_throw(size_t* ntraced) {
21605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  try {
22605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    _Unwind_Backtrace(trace_function, ntraced);
23605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  } catch (...) {
24605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    assert(false);
25605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  }
26605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
27605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
28605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertvoid call3_nothrow(size_t* ntraced) {
29605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  _Unwind_Backtrace(trace_function, ntraced);
30605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
31605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
32605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertvoid call2(size_t* ntraced, bool do_throw) {
33605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  if (do_throw) {
34605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    call3_throw(ntraced);
35605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  } else {
36605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    call3_nothrow(ntraced);
37605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  }
38605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
39605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
40605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertvoid call1(size_t* ntraced, bool do_throw) {
41605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  call2(ntraced, do_throw);
42605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
43605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
44605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albertint main() {
45605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  size_t throw_ntraced = 0;
46605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  size_t nothrow_ntraced = 0;
47605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
48605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  call1(&nothrow_ntraced, false);
49605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
50605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  try {
51605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    call1(&throw_ntraced, true);
52605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  } catch (...) {
53605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert    assert(false);
54605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  }
55605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert
56605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  // Different platforms (and different runtimes) will unwind a different number
57605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  // of times, so we can't make any better assumptions than this.
58605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  assert(nothrow_ntraced > 1);
59605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch
60605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert  return 0;
61605f03260ce43ec564cd0ec80ea21514e82eeeb3Dan Albert}
62