mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Define UB in float-to-int casts to saturate
- Round to zero, and representable values cast directly. - `NaN` goes to 0 - Values beyond the limits of the type are saturated to the "nearest value" (essentially rounding to zero, in some sense) in the integral type, so e.g. `f32::INFINITY` would go to `{u,i}N::MAX.`
This commit is contained in:
parent
a0c61a9044
commit
9907ad6ed9
@ -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;
|
||||
}
|
||||
|
||||
|
@ -558,7 +558,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));
|
||||
|
@ -936,9 +936,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)"),
|
||||
|
@ -1,7 +1,7 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// This file tests that we don't generate any code for saturation when using the
|
||||
// unchecked intrinsics.
|
||||
|
||||
// This file tests that we don't generate any code for saturation if
|
||||
// -Z saturating-float-casts is not enabled.
|
||||
// compile-flags: -C opt-level=3
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
@ -12,7 +12,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
|
||||
@ -22,7 +22,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]
|
||||
@ -31,5 +31,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() }
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
// run-pass
|
||||
// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction.
|
||||
// compile-flags: -Z saturating-float-casts
|
||||
|
||||
#![feature(test, stmt_expr_attributes)]
|
||||
#![deny(overflowing_literals)]
|
||||
|
Loading…
Reference in New Issue
Block a user