about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2019-10-02 21:43:24 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2019-10-02 21:52:15 +0200
commit9fbb2a9b347d44074fff8aab27cd161a9cd54c74 (patch)
treecf95ac2a7c420e3c22ceb2409f9f28e3d4ad6dc9 /src
parent1e869133b9888dc5abde54f4f31cb797ed9c7874 (diff)
downloadrust-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.rs51
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
     });