Apply noundef attribute to all scalar types which do not permit raw init
Beyond `&`/`&mut`/`Box`, this covers `char`, discriminants, `NonZero*`, etc. All such types currently cause a Miri error if left uninitialized, and an `invalid_value` lint in cases like `mem::uninitialized::<char>()` Note that this _does not_ change whether or not it is UB for `u64` (or other integer types with no invalid values) to be undef.
This commit is contained in:
parent
8604ef0878
commit
5979b681e6
@ -3053,6 +3053,11 @@ fn fn_abi_new_uncached(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scalars which have invalid values cannot be undef.
|
||||||
|
if !scalar.is_always_valid(self) {
|
||||||
|
attrs.set(ArgAttribute::NoUndef);
|
||||||
|
}
|
||||||
|
|
||||||
// Only pointer types handled below.
|
// Only pointer types handled below.
|
||||||
if scalar.value != Pointer {
|
if scalar.value != Pointer {
|
||||||
return;
|
return;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// compile-flags: -O
|
||||||
|
|
||||||
#![crate_type="lib"]
|
#![crate_type="lib"]
|
||||||
|
|
||||||
#[repr(i8)]
|
#[repr(i8)]
|
||||||
@ -6,7 +8,7 @@ pub enum Type {
|
|||||||
Type2 = 1
|
Type2 = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: define{{( dso_local)?}} signext i8 @test()
|
// CHECK: define{{( dso_local)?}} noundef signext i8 @test()
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn test() -> Type {
|
pub extern "C" fn test() -> Type {
|
||||||
Type::Type1
|
Type::Type1
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// Checks that range metadata gets emitted on calls to functions returning a
|
// Checks that range metadata gets emitted on calls to functions returning a
|
||||||
// scalar value.
|
// scalar value.
|
||||||
|
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -O -C no-prepopulate-passes
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
pub fn test() {
|
pub fn test() {
|
||||||
// CHECK: call i8 @some_true(), !range [[R0:![0-9]+]]
|
// CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
|
||||||
// CHECK: [[R0]] = !{i8 0, i8 3}
|
// CHECK: [[R0]] = !{i8 0, i8 3}
|
||||||
some_true();
|
some_true();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
pub struct S {
|
pub struct S {
|
||||||
_field: [i32; 8],
|
_field: [i32; 8],
|
||||||
@ -13,6 +14,11 @@ pub struct UnsafeInner {
|
|||||||
_field: std::cell::UnsafeCell<i16>,
|
_field: std::cell::UnsafeCell<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum MyBool {
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x)
|
// CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn boolean(x: bool) -> bool {
|
pub fn boolean(x: bool) -> bool {
|
||||||
@ -25,6 +31,48 @@ pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK: noundef zeroext i1 @enum_bool(i1 noundef zeroext %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn enum_bool(x: MyBool) -> MyBool {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: i8 @maybeuninit_enum_bool(i8 %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: noundef i32 @char(i32 noundef %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn char(x: char) -> char {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: i32 @maybeuninit_char(i32 %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: i64 @int(i64 %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn int(x: u64) -> u64 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: noundef i64 @nonzero_int(i64 noundef %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: i64 @option_nonzero_int(i64 %x)
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK: @readonly_borrow(i32* noalias noundef readonly align 4 dereferenceable(4) %_1)
|
// CHECK: @readonly_borrow(i32* noalias noundef readonly align 4 dereferenceable(4) %_1)
|
||||||
// FIXME #25759 This should also have `nocapture`
|
// FIXME #25759 This should also have `nocapture`
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -156,7 +204,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1)
|
// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
|
pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
|
||||||
x
|
x
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -O -C no-prepopulate-passes
|
||||||
|
|
||||||
// ignore-riscv64 riscv64 has an i128 type used with test_Vector
|
// ignore-riscv64 riscv64 has an i128 type used with test_Vector
|
||||||
// see codegen/riscv-abi for riscv functiona call tests
|
// see codegen/riscv-abi for riscv functiona call tests
|
||||||
@ -56,7 +56,7 @@ pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Bool { True, False, FileNotFound }
|
pub enum Bool { True, False, FileNotFound }
|
||||||
|
|
||||||
// CHECK: define{{( dso_local)?}}{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
|
// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
|
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user