Skip to content

Commit

Permalink
Rollup merge of rust-lang#71269 - Mark-Simulacrum:sat-float-casts, r=…
Browse files Browse the repository at this point in the history
…nikic

Define UB in float-to-int casts to saturate

This closes rust-lang#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.
  • Loading branch information
Dylan-DPC committed May 5, 2020
2 parents f8d394e + d65d179 commit e2911f9
Show file tree
Hide file tree
Showing 6 changed files with 419 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/rvalue.rs
Expand Up @@ -768,7 +768,7 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) -> Bx::Value {
let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) };

if !bx.cx().sess().opts.debugging_opts.saturating_float_casts {
if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts {
return fptosui_result;
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_interface/tests.rs
Expand Up @@ -559,7 +559,7 @@ fn test_debugging_options_tracking_hash() {
tracked!(sanitizer, Some(Sanitizer::Address));
tracked!(sanitizer_memory_track_origins, 2);
tracked!(sanitizer_recover, vec![Sanitizer::Address]);
tracked!(saturating_float_casts, true);
tracked!(saturating_float_casts, Some(true));
tracked!(share_generics, Some(true));
tracked!(show_span, Some(String::from("abc")));
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_session/options.rs
Expand Up @@ -938,9 +938,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable origins tracking in MemorySanitizer"),
sanitizer_recover: Vec<Sanitizer> = (vec![], parse_sanitizer_list, [TRACKED],
"enable recovery for selected sanitizers"),
saturating_float_casts: bool = (false, parse_bool, [TRACKED],
saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
the max/min integer respectively, and NaN is mapped to 0 (default: no)"),
the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
save_analysis: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in JSON format) information, in \
addition to normal output (default: no)"),
Expand Down
7 changes: 0 additions & 7 deletions src/librustc_typeck/check/demand.rs
Expand Up @@ -909,13 +909,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
);
err.warn(
"if the rounded value cannot be represented by the target \
integer type, including `Inf` and `NaN`, casting will cause \
undefined behavior \
(see issue #10184 <https://github.com/rust-lang/rust/issues/10184> \
for more information)",
);
}
true
}
Expand Down
12 changes: 5 additions & 7 deletions src/test/codegen/unchecked-float-casts.rs
@@ -1,7 +1,5 @@
// compile-flags: -C no-prepopulate-passes

// This file tests that we don't generate any code for saturation if
// -Z saturating-float-casts is not enabled.
// This file tests that we don't generate any code for saturation when using the
// unchecked intrinsics.

#![crate_type = "lib"]

Expand All @@ -12,7 +10,7 @@ pub fn f32_to_u32(x: f32) -> u32 {
// CHECK-NOT: fcmp
// CHECK-NOT: icmp
// CHECK-NOT: select
x as u32
unsafe { x.to_int_unchecked() }
}

// CHECK-LABEL: @f32_to_i32
Expand All @@ -22,7 +20,7 @@ pub fn f32_to_i32(x: f32) -> i32 {
// CHECK-NOT: fcmp
// CHECK-NOT: icmp
// CHECK-NOT: select
x as i32
unsafe { x.to_int_unchecked() }
}

#[no_mangle]
Expand All @@ -31,5 +29,5 @@ pub fn f64_to_u16(x: f64) -> u16 {
// CHECK-NOT: fcmp
// CHECK-NOT: icmp
// CHECK-NOT: select
x as u16
unsafe { x.to_int_unchecked() }
}

0 comments on commit e2911f9

Please sign in to comment.