Skip to content

Commit 14d608f

Browse files
authored
Rollup merge of #71269 - Mark-Simulacrum:sat-float-casts, r=nikic
Define UB in float-to-int casts to saturate This closes #10184 by defining the behavior there to saturate infinities and values exceeding the integral range (on the lower or upper end). `NaN` is sent to zero.
2 parents 339f574 + f63b8bf commit 14d608f

File tree

6 files changed

+420
-52
lines changed

6 files changed

+420
-52
lines changed

Diff for: src/librustc_codegen_ssa/mir/rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
768768
) -> Bx::Value {
769769
let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) };
770770

771-
if !bx.cx().sess().opts.debugging_opts.saturating_float_casts {
771+
if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts {
772772
return fptosui_result;
773773
}
774774

Diff for: src/librustc_interface/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ fn test_debugging_options_tracking_hash() {
559559
tracked!(sanitizer, Some(Sanitizer::Address));
560560
tracked!(sanitizer_memory_track_origins, 2);
561561
tracked!(sanitizer_recover, vec![Sanitizer::Address]);
562-
tracked!(saturating_float_casts, true);
562+
tracked!(saturating_float_casts, Some(true));
563563
tracked!(share_generics, Some(true));
564564
tracked!(show_span, Some(String::from("abc")));
565565
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));

Diff for: src/librustc_session/options.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -938,9 +938,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
938938
"enable origins tracking in MemorySanitizer"),
939939
sanitizer_recover: Vec<Sanitizer> = (vec![], parse_sanitizer_list, [TRACKED],
940940
"enable recovery for selected sanitizers"),
941-
saturating_float_casts: bool = (false, parse_bool, [TRACKED],
941+
saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
942942
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
943-
the max/min integer respectively, and NaN is mapped to 0 (default: no)"),
943+
the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
944944
save_analysis: bool = (false, parse_bool, [UNTRACKED],
945945
"write syntax and type analysis (in JSON format) information, in \
946946
addition to normal output (default: no)"),

Diff for: src/librustc_typeck/check/demand.rs

-7
Original file line numberDiff line numberDiff line change
@@ -909,13 +909,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
909909
cast_suggestion,
910910
Applicability::MaybeIncorrect, // lossy conversion
911911
);
912-
err.warn(
913-
"if the rounded value cannot be represented by the target \
914-
integer type, including `Inf` and `NaN`, casting will cause \
915-
undefined behavior \
916-
(see issue #10184 <https://github.com/rust-lang/rust/issues/10184> \
917-
for more information)",
918-
);
919912
}
920913
true
921914
}

Diff for: src/test/codegen/unchecked-float-casts.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// compile-flags: -C no-prepopulate-passes
1+
// This file tests that we don't generate any code for saturation when using the
2+
// unchecked intrinsics.
23

3-
// This file tests that we don't generate any code for saturation if
4-
// -Z saturating-float-casts is not enabled.
4+
// compile-flags: -C opt-level=3
55

66
#![crate_type = "lib"]
77

@@ -12,7 +12,7 @@ pub fn f32_to_u32(x: f32) -> u32 {
1212
// CHECK-NOT: fcmp
1313
// CHECK-NOT: icmp
1414
// CHECK-NOT: select
15-
x as u32
15+
unsafe { x.to_int_unchecked() }
1616
}
1717

1818
// CHECK-LABEL: @f32_to_i32
@@ -22,7 +22,7 @@ pub fn f32_to_i32(x: f32) -> i32 {
2222
// CHECK-NOT: fcmp
2323
// CHECK-NOT: icmp
2424
// CHECK-NOT: select
25-
x as i32
25+
unsafe { x.to_int_unchecked() }
2626
}
2727

2828
#[no_mangle]
@@ -31,5 +31,5 @@ pub fn f64_to_u16(x: f64) -> u16 {
3131
// CHECK-NOT: fcmp
3232
// CHECK-NOT: icmp
3333
// CHECK-NOT: select
34-
x as u16
34+
unsafe { x.to_int_unchecked() }
3535
}

0 commit comments

Comments
 (0)