]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | // Tests that C++ exceptions can unwind through Rust code run destructors and |
2 | // are caught by catch_unwind. Also tests that Rust panics can unwind through | |
e74abb32 XL |
3 | // C++ code. |
4 | ||
5 | // For linking libstdc++ on MinGW | |
6 | #![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))] | |
94222f64 | 7 | #![feature(c_unwind)] |
e74abb32 XL |
8 | |
9 | use std::panic::{catch_unwind, AssertUnwindSafe}; | |
10 | ||
11 | struct DropCheck<'a>(&'a mut bool); | |
12 | impl<'a> Drop for DropCheck<'a> { | |
13 | fn drop(&mut self) { | |
14 | println!("DropCheck::drop"); | |
15 | *self.0 = true; | |
16 | } | |
17 | } | |
18 | ||
19 | extern "C" { | |
1b1a35ee | 20 | fn test_cxx_exception(); |
94222f64 | 21 | } |
e74abb32 | 22 | |
94222f64 XL |
23 | extern "C-unwind" { |
24 | fn cxx_catch_callback(cb: extern "C-unwind" fn(), ok: *mut bool); | |
e74abb32 XL |
25 | } |
26 | ||
27 | #[no_mangle] | |
94222f64 | 28 | extern "C-unwind" fn rust_catch_callback(cb: extern "C-unwind" fn(), rust_ok: &mut bool) { |
1b1a35ee XL |
29 | let _drop = DropCheck(rust_ok); |
30 | cb(); | |
31 | unreachable!("should have unwound instead of returned"); | |
e74abb32 XL |
32 | } |
33 | ||
1b1a35ee | 34 | fn test_rust_panic() { |
94222f64 | 35 | extern "C-unwind" fn callback() { |
e74abb32 XL |
36 | println!("throwing rust panic"); |
37 | panic!(1234i32); | |
38 | } | |
39 | ||
40 | let mut dropped = false; | |
41 | let mut cxx_ok = false; | |
42 | let caught_unwind = catch_unwind(AssertUnwindSafe(|| { | |
43 | let _drop = DropCheck(&mut dropped); | |
44 | unsafe { | |
45 | cxx_catch_callback(callback, &mut cxx_ok); | |
46 | } | |
47 | unreachable!("should have unwound instead of returned"); | |
48 | })); | |
49 | println!("caught rust panic"); | |
50 | assert!(dropped); | |
51 | assert!(caught_unwind.is_err()); | |
52 | let panic_obj = caught_unwind.unwrap_err(); | |
53 | let panic_int = *panic_obj.downcast_ref::<i32>().unwrap(); | |
54 | assert_eq!(panic_int, 1234); | |
55 | assert!(cxx_ok); | |
56 | } | |
57 | ||
58 | fn main() { | |
1b1a35ee XL |
59 | unsafe { test_cxx_exception() }; |
60 | test_rust_panic(); | |
e74abb32 | 61 | } |