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 // _Unwind_ForcedUnwind raised exception can be caught by catch (...) and be 10 // rethrown. If not rethrown, exception_cleanup will be called. 11 12 // UNSUPPORTED: no-exceptions, c++03 13 14 // These tests fail on previously released dylibs, investigation needed. 15 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} 16 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}} 17 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unwind.h> 21 #include <tuple> 22 #include <__cxxabi_config.h> 23 24 static int bits = 0; 25 26 struct C { 27 int bit; 28 C(int b) : bit(b) {} 29 ~C() { bits |= bit; } 30 }; 31 32 template <typename T> 33 struct Stop; 34 35 template <typename R, typename... Args> 36 struct Stop<R (*)(Args...)> { 37 // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM 38 // libunwind while _Unwind_Exception_Class in libgcc. 39 typedef typename std::tuple_element<2, std::tuple<Args...>>::type type; 40 41 static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type, 42 struct _Unwind_Exception*, 43 struct _Unwind_Context*, void*) { 44 if (actions & _UA_END_OF_STACK) 45 abort(); 46 return _URC_NO_REASON; 47 } 48 }; 49 50 static void cleanup(_Unwind_Reason_Code, struct _Unwind_Exception* exc) { 51 bits |= 8; 52 delete exc; 53 } 54 55 static void forced_unwind() { 56 _Unwind_Exception* exc = new _Unwind_Exception; 57 memset(&exc->exception_class, 0, sizeof(exc->exception_class)); 58 exc->exception_cleanup = cleanup; 59 _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0); 60 abort(); 61 } 62 63 static void test() { 64 try { 65 C four(4); 66 try { 67 C one(1); 68 forced_unwind(); 69 } catch (...) { 70 bits |= 2; 71 throw; 72 } 73 } catch (int) { 74 } catch (...) { 75 // __cxa_end_catch calls cleanup. 76 } 77 } 78 79 int main(int, char**) { 80 test(); 81 return bits != 15; 82 } 83