diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2019-10-02 21:43:24 +0200 |
|---|---|---|
| committer | Felix S. Klock II <pnkfelix@pnkfx.org> | 2019-10-02 21:52:15 +0200 |
| commit | 9fbb2a9b347d44074fff8aab27cd161a9cd54c74 (patch) | |
| tree | cf95ac2a7c420e3c22ceb2409f9f28e3d4ad6dc9 /src | |
| parent | 1e869133b9888dc5abde54f4f31cb797ed9c7874 (diff) | |
| download | rust-9fbb2a9b347d44074fff8aab27cd161a9cd54c74.tar.gz rust-9fbb2a9b347d44074fff8aab27cd161a9cd54c74.zip | |
Fix missing calls to drop on unwind with lto=fat; issue 64655.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_codegen_llvm/attributes.rs | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 33b50401b22..4189904a801 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -273,25 +273,50 @@ pub fn from_fn_attrs( } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { // Special attribute for allocator functions, which can't unwind false - } else if let Some(id) = id { + } else if let Some(_) = id { + // rust-lang/rust#64655, rust-lang/rust#63909: to minimize + // risk associated with changing cases where nounwind + // attribute is attached, this code is deliberately mimicking + // old control flow based on whether `id` is `Some` or `None`. + // + // However, in the long term we should either: + // - fold this into final else (i.e. stop inspecting `id`) + // - or better still: whole-heartedly adopt Rust PR #63909. + // + // see also Rust RFC 2753. + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - if cx.tcx.is_foreign_item(id) { - // Foreign items like `extern "C" { fn foo(); }` are assumed not to - // unwind - false - } else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { - // Any items defined in Rust that *don't* have the `extern` ABI are - // defined to not unwind. We insert shims to abort if an unwind - // happens to enforce this. - false - } else { - // Anything else defined in Rust is assumed that it can possibly - // unwind + if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { + // Any Rust method (or `extern "Rust" fn` or `extern + // "rust-call" fn`) is explicitly allowed to unwind + // (unless it has no-unwind attribute, handled above). true + } else { + // Anything else is either: + // + // 1. A foreign item (like `extern "C" { fn foo(); }`), or + // + // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`). + // + // Foreign items (case 1) are assumed to not unwind; it is + // UB otherwise. (At least for now; see also + // rust-lang/rust#63909 and Rust RFC 2753.) + // + // Items defined in Rust with non-Rust ABIs (case 2) are + // defined to not unwind. We insert shims to abort if an + // unwind happens to enforce this. + // + // In either case, we mark item as explicitly nounwind. + false } } else { // assume this can possibly unwind, avoiding the application of a // `nounwind` attribute below. + // + // (But: See comments in previous branch. Specifically, it is + // unclear whether there is real value in the assumption this + // can unwind. The conservatism here may just be papering over + // a real problem by making some UB a bit harder to hit.) true }); |
