Skip to content

Commit 9fbff89

Browse files
committed
Auto merge of #94157 - erikdesjardins:more-noundef, r=nikic
Apply noundef attribute to all scalar types which do not permit raw init Beyond `&`/`&mut`/`Box`, this covers `char`, enum 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. Fixes (partially) #74378. r? `@ghost` (blocked on #94127) `@rustbot` label S-blocked
2 parents 6a70556 + 45ee3fc commit 9fbff89

File tree

6 files changed

+63
-8
lines changed

6 files changed

+63
-8
lines changed

compiler/rustc_middle/src/ty/layout.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
30533053
return;
30543054
}
30553055

3056+
// Scalars which have invalid values cannot be undef.
3057+
if !scalar.is_always_valid(self) {
3058+
attrs.set(ArgAttribute::NoUndef);
3059+
}
3060+
30563061
// Only pointer types handled below.
30573062
if scalar.value != Pointer {
30583063
return;

src/test/codegen/abi-repr-ext.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// compile-flags: -O
2+
13
#![crate_type="lib"]
24

35
#[repr(i8)]
@@ -6,7 +8,7 @@ pub enum Type {
68
Type2 = 1
79
}
810

9-
// CHECK: define{{( dso_local)?}} signext i8 @test()
11+
// CHECK: define{{( dso_local)?}} noundef signext i8 @test()
1012
#[no_mangle]
1113
pub extern "C" fn test() -> Type {
1214
Type::Type1

src/test/codegen/call-metadata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Checks that range metadata gets emitted on calls to functions returning a
22
// scalar value.
33

4-
// compile-flags: -C no-prepopulate-passes
4+
// compile-flags: -O -C no-prepopulate-passes
55

66
#![crate_type = "lib"]
77

88
pub fn test() {
9-
// CHECK: call i8 @some_true(), !range [[R0:![0-9]+]]
9+
// CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
1010
// CHECK: [[R0]] = !{i8 0, i8 3}
1111
some_true();
1212
}

src/test/codegen/function-arguments.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(rustc_attrs)]
55

66
use std::mem::MaybeUninit;
7+
use std::num::NonZeroU64;
78

89
pub struct S {
910
_field: [i32; 8],
@@ -13,6 +14,11 @@ pub struct UnsafeInner {
1314
_field: std::cell::UnsafeCell<i16>,
1415
}
1516

17+
pub enum MyBool {
18+
True,
19+
False,
20+
}
21+
1622
// CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x)
1723
#[no_mangle]
1824
pub fn boolean(x: bool) -> bool {
@@ -25,6 +31,48 @@ pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
2531
x
2632
}
2733

34+
// CHECK: noundef zeroext i1 @enum_bool(i1 noundef zeroext %x)
35+
#[no_mangle]
36+
pub fn enum_bool(x: MyBool) -> MyBool {
37+
x
38+
}
39+
40+
// CHECK: i8 @maybeuninit_enum_bool(i8 %x)
41+
#[no_mangle]
42+
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
43+
x
44+
}
45+
46+
// CHECK: noundef i32 @char(i32 noundef %x)
47+
#[no_mangle]
48+
pub fn char(x: char) -> char {
49+
x
50+
}
51+
52+
// CHECK: i32 @maybeuninit_char(i32 %x)
53+
#[no_mangle]
54+
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
55+
x
56+
}
57+
58+
// CHECK: i64 @int(i64 %x)
59+
#[no_mangle]
60+
pub fn int(x: u64) -> u64 {
61+
x
62+
}
63+
64+
// CHECK: noundef i64 @nonzero_int(i64 noundef %x)
65+
#[no_mangle]
66+
pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 {
67+
x
68+
}
69+
70+
// CHECK: i64 @option_nonzero_int(i64 %x)
71+
#[no_mangle]
72+
pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
73+
x
74+
}
75+
2876
// CHECK: @readonly_borrow(i32* noalias noundef readonly align 4 dereferenceable(4) %_1)
2977
// FIXME #25759 This should also have `nocapture`
3078
#[no_mangle]
@@ -156,7 +204,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] {
156204
x
157205
}
158206

159-
// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1)
207+
// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1)
160208
#[no_mangle]
161209
pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
162210
x

src/test/codegen/repr-transparent.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// compile-flags: -C no-prepopulate-passes
1+
// compile-flags: -O -C no-prepopulate-passes
22

33
// ignore-riscv64 riscv64 has an i128 type used with test_Vector
44
// see codegen/riscv-abi for riscv functiona call tests
@@ -56,7 +56,7 @@ pub struct GenericPlusZst<T>(T, Zst2);
5656
#[repr(u8)]
5757
pub enum Bool { True, False, FileNotFound }
5858

59-
// CHECK: define{{( dso_local)?}}{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
59+
// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1)
6060
#[no_mangle]
6161
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
6262

src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
# First, establish that certain !prof labels are attached to the expected
33
# functions and branching instructions.
44

5-
CHECK: define void @function_called_twice(i32 %c) {{.*}} !prof [[function_called_twice_id:![0-9]+]] {
5+
CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] {
66
CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !prof [[branch_weights0:![0-9]+]]
77

8-
CHECK: define void @function_called_42_times(i32 %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] {
8+
CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] {
99
CHECK: switch i32 %c, label {{.*}} [
1010
CHECK-NEXT: i32 97, label {{.*}}
1111
CHECK-NEXT: i32 98, label {{.*}}

0 commit comments

Comments
 (0)