72 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: no-exceptions10 11// VE only supports SjLj and doesn't provide _Unwind_Backtrace.12// UNSUPPORTED: target={{ve-.*}}13 14#include <assert.h>15#include <stddef.h>16#include <unwind.h>17 18extern "C" _Unwind_Reason_Code19trace_function(struct _Unwind_Context*, void* ntraced) {20 (*reinterpret_cast<size_t*>(ntraced))++;21 // We should never have a call stack this deep...22 assert(*reinterpret_cast<size_t*>(ntraced) < 20);23 return _URC_NO_REASON;24}25 26__attribute__ ((__noinline__))27void call3_throw(size_t* ntraced) {28 try {29 _Unwind_Backtrace(trace_function, ntraced);30 } catch (...) {31 assert(false);32 }33}34 35__attribute__ ((__noinline__, __disable_tail_calls__))36void call3_nothrow(size_t* ntraced) {37 _Unwind_Backtrace(trace_function, ntraced);38}39 40__attribute__ ((__noinline__, __disable_tail_calls__))41void call2(size_t* ntraced, bool do_throw) {42 if (do_throw) {43 call3_throw(ntraced);44 } else {45 call3_nothrow(ntraced);46 }47}48 49__attribute__ ((__noinline__, __disable_tail_calls__))50void call1(size_t* ntraced, bool do_throw) {51 call2(ntraced, do_throw);52}53 54int main(int, char**) {55 size_t throw_ntraced = 0;56 size_t nothrow_ntraced = 0;57 58 call1(¬hrow_ntraced, false);59 60 try {61 call1(&throw_ntraced, true);62 } catch (...) {63 assert(false);64 }65 66 // Different platforms (and different runtimes) will unwind a different number67 // of times, so we can't make any better assumptions than this.68 assert(nothrow_ntraced > 1);69 assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch70 return 0;71}72