summaryrefslogtreecommitdiffstats
path: root/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic')
-rw-r--r--tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile30
-rw-r--r--tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c12
-rw-r--r--tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs35
-rw-r--r--tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs12
4 files changed, 89 insertions, 0 deletions
diff --git a/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile
new file mode 100644
index 000000000..134f000d4
--- /dev/null
+++ b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/Makefile
@@ -0,0 +1,30 @@
+include ../tools.mk
+
+all: archive
+ # Compile `main.rs`, which will link into our library, and run it.
+ $(RUSTC) main.rs
+ $(call RUN,main)
+
+ifdef IS_MSVC
+archive: add.o panic.o
+ # Now, create an archive using these two objects.
+ $(AR) crus $(TMPDIR)/add.lib $(TMPDIR)/add.o $(TMPDIR)/panic.o
+else
+archive: add.o panic.o
+ # Now, create an archive using these two objects.
+ $(AR) crus $(TMPDIR)/libadd.a $(TMPDIR)/add.o $(TMPDIR)/panic.o
+endif
+
+# Compile `panic.rs` into an object file.
+#
+# Note that we invoke `rustc` directly, so we may emit an object rather
+# than an archive. We'll do that later.
+panic.o:
+ $(BARE_RUSTC) $(RUSTFLAGS) \
+ --out-dir $(TMPDIR) \
+ --emit=obj panic.rs
+
+# Compile `add.c` into an object file.
+add.o:
+ $(call COMPILE_OBJ,$(TMPDIR)/add.o,add.c)
+
diff --git a/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c
new file mode 100644
index 000000000..444359451
--- /dev/null
+++ b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/add.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+
+// An external function, defined in Rust.
+extern void panic_if_greater_than_10(unsigned x);
+
+unsigned add_small_numbers(unsigned a, unsigned b) {
+ unsigned c = a + b;
+ panic_if_greater_than_10(c);
+ return c;
+}
diff --git a/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs
new file mode 100644
index 000000000..78a71219c
--- /dev/null
+++ b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/main.rs
@@ -0,0 +1,35 @@
+//! A test for calling `C-unwind` functions across foreign function boundaries.
+//!
+//! This test triggers a panic in a Rust library that our foreign function invokes. This shows
+//! that we can unwind through the C code in that library, and catch the underlying panic.
+#![feature(c_unwind)]
+
+use std::panic::{catch_unwind, AssertUnwindSafe};
+
+fn main() {
+ // Call `add_small_numbers`, passing arguments that will NOT trigger a panic.
+ let (a, b) = (9, 1);
+ let c = unsafe { add_small_numbers(a, b) };
+ assert_eq!(c, 10);
+
+ // Call `add_small_numbers`, passing arguments that will trigger a panic, and catch it.
+ let caught_unwind = catch_unwind(AssertUnwindSafe(|| {
+ let (a, b) = (10, 1);
+ let _c = unsafe { add_small_numbers(a, b) };
+ unreachable!("should have unwound instead of returned");
+ }));
+
+ // Assert that we did indeed panic, then unwrap and downcast the panic into the sum.
+ assert!(caught_unwind.is_err());
+ let panic_obj = caught_unwind.unwrap_err();
+ let msg = panic_obj.downcast_ref::<String>().unwrap();
+ assert_eq!(msg, "11");
+}
+
+#[link(name = "add", kind = "static")]
+extern "C-unwind" {
+ /// An external function, defined in C.
+ ///
+ /// Returns the sum of two numbers, or panics if the sum is greater than 10.
+ fn add_small_numbers(a: u32, b: u32) -> u32;
+}
diff --git a/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs
new file mode 100644
index 000000000..a99a04d5c
--- /dev/null
+++ b/tests/run-make-fulldeps/c-unwind-abi-catch-lib-panic/panic.rs
@@ -0,0 +1,12 @@
+#![crate_type = "staticlib"]
+#![feature(c_unwind)]
+
+/// This function will panic if `x` is greater than 10.
+///
+/// This function is called by `add_small_numbers`.
+#[no_mangle]
+pub extern "C-unwind" fn panic_if_greater_than_10(x: u32) {
+ if x > 10 {
+ panic!("{}", x); // That is too big!
+ }
+}