[libcxx-commits] [libcxxabi] 81af814 - [test] Add basic _Unwind_ForcedUnwind + exception tests

Fangrui Song via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 2 09:35:34 PST 2021


Author: Fangrui Song
Date: 2021-02-02T09:35:27-08:00
New Revision: 81af8149d8cb8ff65f2569d813252fab2a14df00

URL: https://github.com/llvm/llvm-project/commit/81af8149d8cb8ff65f2569d813252fab2a14df00
DIFF: https://github.com/llvm/llvm-project/commit/81af8149d8cb8ff65f2569d813252fab2a14df00.diff

LOG: [test] Add basic _Unwind_ForcedUnwind + exception tests

Forced unwinding is like a foreign exception, which can be caught by `catch (...)` and rethrown.
If not rethrown, `__cxa_end_cath` will call `_Unwind_DeleteException` to destroy the object.

The behavior going through empty `throw()` and non-empty `throw(int)` is not
clear (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98785), so I do not add such
tests.

Differential Revision: https://reviews.llvm.org/D95200

Added: 
    libcxxabi/test/forced_unwind1.pass.cpp
    libcxxabi/test/forced_unwind2.pass.cpp

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/libcxxabi/test/forced_unwind1.pass.cpp b/libcxxabi/test/forced_unwind1.pass.cpp
new file mode 100644
index 000000000000..9432f48677d5
--- /dev/null
+++ b/libcxxabi/test/forced_unwind1.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// _Unwind_ForcedUnwind raised exception can be caught by catch (...) and be
+// rethrown. If not rethrown, exception_cleanup will be called.
+
+// UNSUPPORTED: no-exceptions, c++03
+
+#include <stdlib.h>
+#include <string.h>
+#include <unwind.h>
+#include <tuple>
+
+static int bits = 0;
+
+struct C {
+  int bit;
+  C(int b) : bit(b) {}
+  ~C() { bits |= bit; }
+};
+
+template <typename T>
+struct Stop;
+
+template <typename R, typename... Args>
+struct Stop<R (*)(Args...)> {
+  // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
+  // libunwind while _Unwind_Exception_Class in libgcc.
+  typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
+
+  static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type,
+                                  struct _Unwind_Exception*,
+                                  struct _Unwind_Context*, void*) {
+    if (actions & _UA_END_OF_STACK)
+      abort();
+    return _URC_NO_REASON;
+  }
+};
+
+static void cleanup(_Unwind_Reason_Code, struct _Unwind_Exception* exc) {
+  bits |= 8;
+  delete exc;
+}
+
+static void forced_unwind() {
+  _Unwind_Exception* exc = new _Unwind_Exception;
+  exc->exception_class = 0;
+  exc->exception_cleanup = cleanup;
+  _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
+  abort();
+}
+
+static void test() {
+  try {
+    C four(4);
+    try {
+      C one(1);
+      forced_unwind();
+    } catch (...) {
+      bits |= 2;
+      throw;
+    }
+  } catch (int) {
+  } catch (...) {
+    // __cxa_end_catch calls cleanup.
+  }
+}
+
+int main() {
+  test();
+  return bits != 15;
+}

diff  --git a/libcxxabi/test/forced_unwind2.pass.cpp b/libcxxabi/test/forced_unwind2.pass.cpp
new file mode 100644
index 000000000000..4eb9f48ca6b8
--- /dev/null
+++ b/libcxxabi/test/forced_unwind2.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Forced unwinding causes std::terminate when going through noexcept.
+
+// UNSUPPORTED: no-exceptions, c++03
+
+#include <exception>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unwind.h>
+#include <tuple>
+
+template <typename T>
+struct Stop;
+
+template <typename R, typename... Args>
+struct Stop<R (*)(Args...)> {
+  // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
+  // libunwind while _Unwind_Exception_Class in libgcc.
+  typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
+
+  static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type,
+                                  struct _Unwind_Exception*,
+                                  struct _Unwind_Context*, void*) {
+    if (actions & _UA_END_OF_STACK)
+      abort();
+    return _URC_NO_REASON;
+  }
+};
+
+static void forced_unwind() {
+  _Unwind_Exception* exc = new _Unwind_Exception;
+  exc->exception_class = 0;
+  exc->exception_cleanup = 0;
+  _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
+  abort();
+}
+
+static void test() noexcept { forced_unwind(); }
+
+static void terminate() { exit(0); }
+
+int main() {
+  std::set_terminate(terminate);
+  try {
+    test();
+  } catch (...) {
+  }
+  abort();
+}


        


More information about the libcxx-commits mailing list