Skip to content

Commit 9fbb2a9

Browse files
committed
Fix missing calls to drop on unwind with lto=fat; issue 64655.
1 parent 1e86913 commit 9fbb2a9

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

src/librustc_codegen_llvm/attributes.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,25 +273,50 @@ pub fn from_fn_attrs(
273273
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
274274
// Special attribute for allocator functions, which can't unwind
275275
false
276-
} else if let Some(id) = id {
276+
} else if let Some(_) = id {
277+
// rust-lang/rust#64655, rust-lang/rust#63909: to minimize
278+
// risk associated with changing cases where nounwind
279+
// attribute is attached, this code is deliberately mimicking
280+
// old control flow based on whether `id` is `Some` or `None`.
281+
//
282+
// However, in the long term we should either:
283+
// - fold this into final else (i.e. stop inspecting `id`)
284+
// - or better still: whole-heartedly adopt Rust PR #63909.
285+
//
286+
// see also Rust RFC 2753.
287+
277288
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
278-
if cx.tcx.is_foreign_item(id) {
279-
// Foreign items like `extern "C" { fn foo(); }` are assumed not to
280-
// unwind
281-
false
282-
} else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall {
283-
// Any items defined in Rust that *don't* have the `extern` ABI are
284-
// defined to not unwind. We insert shims to abort if an unwind
285-
// happens to enforce this.
286-
false
287-
} else {
288-
// Anything else defined in Rust is assumed that it can possibly
289-
// unwind
289+
if sig.abi == Abi::Rust || sig.abi == Abi::RustCall {
290+
// Any Rust method (or `extern "Rust" fn` or `extern
291+
// "rust-call" fn`) is explicitly allowed to unwind
292+
// (unless it has no-unwind attribute, handled above).
290293
true
294+
} else {
295+
// Anything else is either:
296+
//
297+
// 1. A foreign item (like `extern "C" { fn foo(); }`), or
298+
//
299+
// 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
300+
//
301+
// Foreign items (case 1) are assumed to not unwind; it is
302+
// UB otherwise. (At least for now; see also
303+
// rust-lang/rust#63909 and Rust RFC 2753.)
304+
//
305+
// Items defined in Rust with non-Rust ABIs (case 2) are
306+
// defined to not unwind. We insert shims to abort if an
307+
// unwind happens to enforce this.
308+
//
309+
// In either case, we mark item as explicitly nounwind.
310+
false
291311
}
292312
} else {
293313
// assume this can possibly unwind, avoiding the application of a
294314
// `nounwind` attribute below.
315+
//
316+
// (But: See comments in previous branch. Specifically, it is
317+
// unclear whether there is real value in the assumption this
318+
// can unwind. The conservatism here may just be papering over
319+
// a real problem by making some UB a bit harder to hit.)
295320
true
296321
});
297322

0 commit comments

Comments
 (0)