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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Forced unwinding causes std::terminate when going through noexcept.
10 
11 // UNSUPPORTED: no-exceptions, c++03
12 
13 #include <exception>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <unwind.h>
18 #include <tuple>
19 
20 #if defined(_LIBCXXABI_ARM_EHABI)
21 int main() {}
22 #else
23 template <typename T>
24 struct Stop;
25 
26 template <typename R, typename... Args>
27 struct Stop<R (*)(Args...)> {
28   // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
29   // libunwind while _Unwind_Exception_Class in libgcc.
30   typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
31 
32   static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type,
33                                   struct _Unwind_Exception*,
34                                   struct _Unwind_Context*, void*) {
35     if (actions & _UA_END_OF_STACK)
36       abort();
37     return _URC_NO_REASON;
38   }
39 };
40 
41 static void forced_unwind() {
42   _Unwind_Exception* exc = new _Unwind_Exception;
43   exc->exception_class = 0;
44   exc->exception_cleanup = 0;
45   _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
46   abort();
47 }
48 
49 static void test() noexcept { forced_unwind(); }
50 
51 static void terminate() { exit(0); }
52 
53 int main() {
54   std::set_terminate(terminate);
55   try {
56     test();
57   } catch (...) {
58   }
59   abort();
60 }
61 #endif
62