blob: 77c447c607f4f1799226ebde99a7655168d63b25 [file] [log] [blame]
Dan Albert2c012d42014-08-29 15:26:06 +00001//===---------------------- backtrace_test.cpp ----------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// 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
Dan Albert2c012d42014-08-29 15:26:06 +00006//
7//===----------------------------------------------------------------------===//
Asiri Rathnayake57e446d2016-05-31 12:01:32 +00008
Louis Dionne8c611142020-04-17 10:29:15 -04009// UNSUPPORTED: no-exceptions
Asiri Rathnayake57e446d2016-05-31 12:01:32 +000010
Dan Albert2c012d42014-08-29 15:26:06 +000011#include <assert.h>
Dan Alberte5f15212014-08-29 16:09:32 +000012#include <stddef.h>
Dan Albert2c012d42014-08-29 15:26:06 +000013#include <unwind.h>
14
15extern "C" _Unwind_Reason_Code
Eric Fiseliera140cba2016-12-24 00:37:13 +000016trace_function(struct _Unwind_Context*, void* ntraced) {
Dan Albert2c012d42014-08-29 15:26:06 +000017 (*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
Saleem Abdulrasool0b7b36a2016-08-28 18:16:00 +000023__attribute__ ((__noinline__))
Dan Albert2c012d42014-08-29 15:26:06 +000024void call3_throw(size_t* ntraced) {
25 try {
26 _Unwind_Backtrace(trace_function, ntraced);
27 } catch (...) {
28 assert(false);
29 }
30}
31
Saleem Abdulrasool0b7b36a2016-08-28 18:16:00 +000032__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert2c012d42014-08-29 15:26:06 +000033void call3_nothrow(size_t* ntraced) {
34 _Unwind_Backtrace(trace_function, ntraced);
35}
36
Saleem Abdulrasool0b7b36a2016-08-28 18:16:00 +000037__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert2c012d42014-08-29 15:26:06 +000038void call2(size_t* ntraced, bool do_throw) {
39 if (do_throw) {
40 call3_throw(ntraced);
41 } else {
42 call3_nothrow(ntraced);
43 }
44}
45
Saleem Abdulrasool0b7b36a2016-08-28 18:16:00 +000046__attribute__ ((__noinline__, __disable_tail_calls__))
Dan Albert2c012d42014-08-29 15:26:06 +000047void call1(size_t* ntraced, bool do_throw) {
48 call2(ntraced, do_throw);
49}
50
Louis Dionne504bc072020-10-08 13:36:33 -040051int main(int, char**) {
Dan Albert2c012d42014-08-29 15:26:06 +000052 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
Dan Albert2c012d42014-08-29 15:26:06 +000067 return 0;
68}