//@ run-pass //@ needs-unwind //@ ignore-emscripten no threads support // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, // bugs with how the nounwind LLVM attribute was applied led to this // simple case being mishandled *if* you had fat LTO turned on. // Unlike issue-64655-extern-rust-must-allow-unwind.rs, the issue // embodied in this test cropped up regardless of optimization level. // Therefore it seemed worthy of being enshrined as a dedicated unit // test. // LTO settings cannot be combined with -C prefer-dynamic //@ no-prefer-dynamic // The revisions just enumerate lto settings (the opt-level appeared irrelevant in practice) //@ revisions: no thin fat //@[no]compile-flags: -C lto=no //@[thin]compile-flags: -C lto=thin //@[fat]compile-flags: -C lto=fat #![feature(panic_internals)] // (For some reason, reproducing the LTO issue requires pulling in std // explicitly this way.) #![no_std] extern crate std; fn main() { use std::sync::atomic::{AtomicUsize, Ordering}; use std::boxed::Box; static SHARED: AtomicUsize = AtomicUsize::new(0); assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); let old_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. let handle = std::thread::spawn(|| { struct Droppable; impl Drop for Droppable { fn drop(&mut self) { SHARED.fetch_add(1, Ordering::SeqCst); } } let _guard = Droppable; core::panicking::panic("???"); }); let wait = handle.join(); // Reinstate handler to ease observation of assertion failures. std::panic::set_hook(old_hook); assert!(wait.is_err()); assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); }