about summary refs log tree commit diff
path: root/src/librustc_codegen_ssa
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-04-04 15:09:04 +0200
committerGitHub <noreply@github.com>2019-04-04 15:09:04 +0200
commit05c31baf83ffe6f96ee379d00a236356ce39fd6d (patch)
treefd21ae4442c99cc154c885b3a2ef29b05f78138d /src/librustc_codegen_ssa
parent56328a595201285fcafc07835a64799cf59171f4 (diff)
parentc2e0d7f1eb25bd9b4a8eaa7990cd0fd3a8c416bb (diff)
downloadrust-05c31baf83ffe6f96ee379d00a236356ce39fd6d.tar.gz
rust-05c31baf83ffe6f96ee379d00a236356ce39fd6d.zip
Rollup merge of #59639 - cuviper:ignore-uninhabited, r=eddyb
Never return uninhabited values at all

Functions with uninhabited return values are already marked `noreturn`,
but we were still generating return instructions for this. When running
with `-C passes=lint`, LLVM prints:

    Unusual: Return statement in function with noreturn attribute

The LLVM manual makes a stronger statement about `noreturn` though:

> This produces undefined behavior at runtime if the function ever does
dynamically return.

We now emit an `abort` anywhere that would have tried to return an
uninhabited value.

Fixes #48227
cc #7463 #48229

r? @eddyb
Diffstat (limited to 'src/librustc_codegen_ssa')
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 65f7e023fa2..e64c847db65 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -238,6 +238,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
         }
+        if self.fn_ty.ret.layout.abi.is_uninhabited() {
+            // Functions with uninhabited return values are marked `noreturn`,
+            // so we should make sure that we never actually do.
+            bx.abort();
+            bx.unreachable();
+            return;
+        }
         let llval = match self.fn_ty.ret.mode {
             PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => {
                 bx.ret_void();