]> git.lizzy.rs Git - rust.git/blob - src/test/run-make-fulldeps/foreign-exceptions/foo.rs
Rollup merge of #67784 - Mark-Simulacrum:residual-pad-integral, r=dtolnay
[rust.git] / src / test / run-make-fulldeps / foreign-exceptions / foo.rs
1 // Tests that C++ exceptions can unwind through Rust code, run destructors and
2 // are ignored by catch_unwind. Also tests that Rust panics can unwind through
3 // C++ code.
4
5 // For linking libstdc++ on MinGW
6 #![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
7 #![feature(unwind_attributes)]
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" {
20     fn throw_cxx_exception();
21
22     #[unwind(allowed)]
23     fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
24 }
25
26 #[no_mangle]
27 #[unwind(allowed)]
28 extern "C" fn rust_catch_callback(cb: extern "C" fn(), rust_ok: &mut bool) {
29     let _caught_unwind = catch_unwind(AssertUnwindSafe(|| {
30         let _drop = DropCheck(rust_ok);
31         cb();
32         unreachable!("should have unwound instead of returned");
33     }));
34     unreachable!("catch_unwind should not have caught foreign exception");
35 }
36
37 fn throw_rust_panic() {
38     #[unwind(allowed)]
39     extern "C" fn callback() {
40         println!("throwing rust panic");
41         panic!(1234i32);
42     }
43
44     let mut dropped = false;
45     let mut cxx_ok = false;
46     let caught_unwind = catch_unwind(AssertUnwindSafe(|| {
47         let _drop = DropCheck(&mut dropped);
48         unsafe {
49             cxx_catch_callback(callback, &mut cxx_ok);
50         }
51         unreachable!("should have unwound instead of returned");
52     }));
53     println!("caught rust panic");
54     assert!(dropped);
55     assert!(caught_unwind.is_err());
56     let panic_obj = caught_unwind.unwrap_err();
57     let panic_int = *panic_obj.downcast_ref::<i32>().unwrap();
58     assert_eq!(panic_int, 1234);
59     assert!(cxx_ok);
60 }
61
62 fn main() {
63     unsafe { throw_cxx_exception() };
64     throw_rust_panic();
65 }