]> git.lizzy.rs Git - rust.git/blob - tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
Rollup merge of #106427 - mejrs:translation_errors, r=davidtwco
[rust.git] / tests / ui / extern / issue-64655-extern-rust-must-allow-unwind.rs
1 // run-pass
2 // needs-unwind
3 // ignore-emscripten no threads support
4
5 // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
6 // should still run destructors as it unwinds the stack. However,
7 // bugs with how the nounwind LLVM attribute was applied led to this
8 // simple case being mishandled *if* you had optimization *and* fat
9 // LTO turned on.
10
11 // This test is the closest thing to a "regression test" we can do
12 // without actually spawning subprocesses and comparing stderr
13 // results.
14 //
15 // This test takes the code from the above issue and adapts it to
16 // better fit our test infrastructure:
17 //
18 // * Instead of relying on `println!` to observe whether the destructor
19 //   is run, we instead run the code in a spawned thread and
20 //   communicate the destructor's operation via a synchronous atomic
21 //   in static memory.
22 //
23 // * To keep the output from confusing a casual user, we override the
24 //   panic hook to be a no-op (rather than printing a message to
25 //   stderr).
26 //
27 // (pnkfelix has confirmed by hand that these additions do not mask
28 // the underlying bug.)
29
30 // LTO settings cannot be combined with -C prefer-dynamic
31 // no-prefer-dynamic
32
33 // The revisions combine each lto setting with each optimization
34 // setting; pnkfelix observed three differing behaviors at opt-levels
35 // 0/1/2+3 for this test, so it seems prudent to be thorough.
36
37 // revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2  fat3
38
39 //[no0]compile-flags: -C opt-level=0 -C lto=no
40 //[no1]compile-flags: -C opt-level=1 -C lto=no
41 //[no2]compile-flags: -C opt-level=2 -C lto=no
42 //[no3]compile-flags: -C opt-level=3 -C lto=no
43 //[thin0]compile-flags: -C opt-level=0 -C lto=thin
44 //[thin1]compile-flags: -C opt-level=1 -C lto=thin
45 //[thin2]compile-flags: -C opt-level=2 -C lto=thin
46 //[thin3]compile-flags: -C opt-level=3 -C lto=thin
47 //[fat0]compile-flags: -C opt-level=0 -C lto=fat
48 //[fat1]compile-flags: -C opt-level=1 -C lto=fat
49 //[fat2]compile-flags: -C opt-level=2 -C lto=fat
50 //[fat3]compile-flags: -C opt-level=3 -C lto=fat
51
52 fn main() {
53     use std::sync::atomic::{AtomicUsize, Ordering};
54
55     static SHARED: AtomicUsize = AtomicUsize::new(0);
56
57     assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0);
58
59     let old_hook = std::panic::take_hook();
60
61     std::panic::set_hook(Box::new(|_| { } )); // no-op on panic.
62
63     let handle = std::thread::spawn(|| {
64         struct Droppable;
65         impl Drop for Droppable {
66             fn drop(&mut self) {
67                 SHARED.fetch_add(1, Ordering::SeqCst);
68             }
69         }
70
71         let _guard = Droppable;
72         None::<()>.expect("???");
73     });
74
75     let wait = handle.join();
76
77     // reinstate handler to ease observation of assertion failures.
78     std::panic::set_hook(old_hook);
79
80     assert!(wait.is_err());
81
82     assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1);
83 }