diff options
| author | Josh Stone <jistone@redhat.com> | 2019-04-03 15:44:49 -0700 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2019-04-03 15:44:49 -0700 |
| commit | c2e0d7f1eb25bd9b4a8eaa7990cd0fd3a8c416bb (patch) | |
| tree | f9e3adc79aa84e1dc9059233e789da70ea05ff05 /src/test/codegen | |
| parent | e008e4fde837313d4a72da603ef492a721afc998 (diff) | |
| download | rust-c2e0d7f1eb25bd9b4a8eaa7990cd0fd3a8c416bb.tar.gz rust-c2e0d7f1eb25bd9b4a8eaa7990cd0fd3a8c416bb.zip | |
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.
Diffstat (limited to 'src/test/codegen')
| -rw-r--r-- | src/test/codegen/noreturn-uninhabited.rs | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/test/codegen/noreturn-uninhabited.rs b/src/test/codegen/noreturn-uninhabited.rs new file mode 100644 index 00000000000..1b65da9f287 --- /dev/null +++ b/src/test/codegen/noreturn-uninhabited.rs @@ -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 |
