Skip to content

Commit 645c0fd

Browse files
committed
Put noundef on all scalars that don't allow uninit
Previously, it was only put on scalars with range validity invariants like bool, was uninit was obviously invalid for those. Since then, we have normatively declared all uninit primitives to be undefined behavior and can therefore put `noundef` on them. The remaining concern was the `mem::uninitialized` function, which cause quite a lot of UB in the older parts of the ecosystem. This function now doesn't return uninit values anymore, making users of it safe from this change. The only real sources of UB where people could encounter uninit primitives are `MaybeUninit::uninit().assume_init()`, which has always be clear in the docs about being UB and from heap allocations (like reading from the spare capacity of a vec. This is hopefully rare enough to not break anything.
1 parent 4781233 commit 645c0fd

35 files changed

+176
-176
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
501501
layout: TyAndLayout<'tcx>,
502502
offset: Size,
503503
) {
504-
if !scalar.is_always_valid(bx) {
504+
if !scalar.is_uninit_valid() {
505505
bx.noundef_metadata(load);
506506
}
507507

compiler/rustc_ty_utils/src/abi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ fn adjust_for_rust_scalar<'tcx>(
220220
}
221221

222222
// Scalars which have invalid values cannot be undef.
223-
if !scalar.is_always_valid(&cx) {
223+
if !scalar.is_uninit_valid() {
224224
attrs.set(ArgAttribute::NoUndef);
225225
}
226226

tests/codegen/abi-sysv64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ trait Sized {}
1515
trait Copy {}
1616
impl Copy for i64 {}
1717

18-
// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
18+
// CHECK: define x86_64_sysvcc noundef i64 @has_sysv64_abi
1919
#[no_mangle]
2020
pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
2121
a

tests/codegen/abi-x86-interrupt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ trait Sized {}
1515
trait Copy {}
1616
impl Copy for i64 {}
1717

18-
// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi
18+
// CHECK: define x86_intrcc noundef i64 @has_x86_interrupt_abi
1919
#[no_mangle]
2020
pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 {
2121
a

tests/codegen/adjustments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![crate_type = "lib"]
44

55
// Hack to get the correct size for the length part in slices
6-
// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
6+
// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1)
77
#[no_mangle]
88
pub fn helper(_: usize) {
99
}

tests/codegen/box-maybe-uninit-llvm14.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
3131
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
3232
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
3333
// on all of them being set until LLVM 15.
34-
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+.*}})
34+
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)

tests/codegen/box-maybe-uninit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
2828

2929
// Hide the `allocalign` attribute in the declaration of __rust_alloc
3030
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
31-
// CHECK: declare noalias ptr @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+}} allocalign) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
31+
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
3232

3333
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }

tests/codegen/c-variadic.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern "C" {
1515

1616
pub unsafe extern "C" fn use_foreign_c_variadic_0() {
1717
// Ensure that we correctly call foreign C-variadic functions.
18-
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
18+
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM:i32 noundef( signext)?]] 0)
1919
foreign_c_variadic_0(0);
2020
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
2121
foreign_c_variadic_0(0, 42i32);
@@ -61,7 +61,7 @@ pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
6161
// Ensure that we generate the correct `call` signature when calling a Rust
6262
// defined C-variadic.
6363
pub unsafe fn test_c_variadic_call() {
64-
// CHECK: call [[RET:(signext )?i32]] (i32, ...) @c_variadic([[PARAM]] 0)
64+
// CHECK: call [[RET:noundef( signext)? i32]] (i32, ...) @c_variadic([[PARAM]] 0)
6565
c_variadic(0);
6666
// CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42)
6767
c_variadic(0, 42i32);

tests/codegen/call-llvm-intrinsics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn do_call() {
2323

2424
unsafe {
2525
// Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
26-
// CHECK: call float @llvm.sqrt.f32(float 4.000000e+00
26+
// CHECK: call noundef float @llvm.sqrt.f32(float noundef 4.000000e+00
2727
sqrt(4.0);
2828
}
2929
}

tests/codegen/comparison-operators-newtype.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::cmp::Ordering;
1313
pub struct Foo(u16);
1414

1515
// CHECK-LABEL: @check_lt
16-
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
16+
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
1717
#[no_mangle]
1818
pub fn check_lt(a: Foo, b: Foo) -> bool {
1919
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
@@ -22,7 +22,7 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
2222
}
2323

2424
// CHECK-LABEL: @check_le
25-
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
25+
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
2626
#[no_mangle]
2727
pub fn check_le(a: Foo, b: Foo) -> bool {
2828
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
@@ -31,7 +31,7 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
3131
}
3232

3333
// CHECK-LABEL: @check_gt
34-
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
34+
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
3535
#[no_mangle]
3636
pub fn check_gt(a: Foo, b: Foo) -> bool {
3737
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
@@ -40,7 +40,7 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
4040
}
4141

4242
// CHECK-LABEL: @check_ge
43-
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
43+
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
4444
#[no_mangle]
4545
pub fn check_ge(a: Foo, b: Foo) -> bool {
4646
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]

0 commit comments

Comments
 (0)