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
This commit is contained in:
commit
05c31baf83
2 changed files with 39 additions and 0 deletions
|
@ -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();
|
||||
|
|
32
src/test/codegen/noreturn-uninhabited.rs
Normal file
32
src/test/codegen/noreturn-uninhabited.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
// compile-flags: -g -C no-prepopulate-passes
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum EmptyEnum {}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn empty(x: &EmptyEnum) -> EmptyEnum {
|
||||
// CHECK: @empty({{.*}}) unnamed_addr #0
|
||||
// CHECK-NOT: ret void
|
||||
// CHECK: call void @llvm.trap()
|
||||
// CHECK: unreachable
|
||||
*x
|
||||
}
|
||||
|
||||
pub struct Foo(String, EmptyEnum);
|
||||
|
||||
#[no_mangle]
|
||||
pub fn foo(x: String, y: &EmptyEnum) -> Foo {
|
||||
// CHECK: @foo({{.*}}) unnamed_addr #0
|
||||
// CHECK-NOT: ret %Foo
|
||||
// CHECK: call void @llvm.trap()
|
||||
// CHECK: unreachable
|
||||
Foo(x, *y)
|
||||
}
|
||||
|
||||
// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
|
||||
|
||||
// CHECK: DISubprogram(name: "empty", {{.*}} DIFlagNoReturn
|
||||
// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
|
Loading…
Add table
Add a link
Reference in a new issue