blob: b9388ff67ba3e3baa0f21e655ebced38a67e1cab [file] [log] [blame]
Dan Albert14690902014-08-29 15:26:06 +00001//===---------------------- 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//===----------------------------------------------------------------------===//
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +00009
10// UNSUPPORTED: libcxxabi-no-exceptions
11
Dan Albert14690902014-08-29 15:26:06 +000012#include <assert.h>
Dan Alberta3a836a2014-08-29 16:09:32 +000013#include <stddef.h>
Dan Albert14690902014-08-29 15:26:06 +000014#include <unwind.h>
15
16extern "C" _Unwind_Reason_Code
Eric Fiselier08bf03c2016-12-24 00:37:13 +000017trace_function(struct _Unwind_Context*, void* ntraced) {
Dan Albert14690902014-08-29 15:26:06 +000018 (*reinterpret_cast<size_t*>(ntraced))++;
19 // We should never have a call stack this deep...
20 assert(*reinterpret_cast<size_t*>(ntraced) < 20);
21 return _URC_NO_REASON;
22}
23
Saleem Abdulrasool866c52a2016-08-28 18:16:00 +000024__attribute__ ((__noinline__))
Dan Albert14690902014-08-29 15:26:06 +000025void call3_throw(size_t* ntraced) {
26 try {
27 _Unwind_Backtrace(trace_function, ntraced);
28 } catch (...) {
29 assert(false);
30 }
31}
32
Saleem Abdulrasool866c52a2016-08-28 18:16:00 +000033__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert14690902014-08-29 15:26:06 +000034void call3_nothrow(size_t* ntraced) {
35 _Unwind_Backtrace(trace_function, ntraced);
36}
37
Saleem Abdulrasool866c52a2016-08-28 18:16:00 +000038__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert14690902014-08-29 15:26:06 +000039void call2(size_t* ntraced, bool do_throw) {
40 if (do_throw) {
41 call3_throw(ntraced);
42 } else {
43 call3_nothrow(ntraced);
44 }
45}
46
Saleem Abdulrasool866c52a2016-08-28 18:16:00 +000047__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert14690902014-08-29 15:26:06 +000048void call1(size_t* ntraced, bool do_throw) {
49 call2(ntraced, do_throw);
50}
51
52int main() {
53 size_t throw_ntraced = 0;
54 size_t nothrow_ntraced = 0;
55
56 call1(&nothrow_ntraced, false);
57
58 try {
59 call1(&throw_ntraced, true);
60 } catch (...) {
61 assert(false);
62 }
63
64 // Different platforms (and different runtimes) will unwind a different number
65 // of times, so we can't make any better assumptions than this.
66 assert(nothrow_ntraced > 1);
67 assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch
Dan Albert14690902014-08-29 15:26:06 +000068 return 0;
69}