about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2020-04-17 21:42:22 -0400
committerMark Rousskov <mark.simulacrum@gmail.com>2020-05-06 08:14:21 -0400
commit9907ad6ed9fde5ccdb58a7d59d652a4c8a98a346 (patch)
tree7470f8e3ea081729bd155d40dab7310f601c5940 /src
parenta0c61a904482129989f5c1e5cb9f1008efb76f7f (diff)
downloadrust-9907ad6ed9fde5ccdb58a7d59d652a4c8a98a346.tar.gz
rust-9907ad6ed9fde5ccdb58a7d59d652a4c8a98a346.zip
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.`
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs2
-rw-r--r--src/librustc_interface/tests.rs2
-rw-r--r--src/librustc_session/options.rs4
-rw-r--r--src/test/codegen/unchecked-float-casts.rs12
-rw-r--r--src/test/ui/numbers-arithmetic/saturating-float-casts.rs1
5 files changed, 10 insertions, 11 deletions
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 19a0138d9cb..bb532abd84b 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -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;
     }
 
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 0a200426e38..ad1934c9786 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -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));
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index b03fc00d93d..7fcf6d13850 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -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)"),
diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs
index 34e96122223..789feea12d6 100644
--- a/src/test/codegen/unchecked-float-casts.rs
+++ b/src/test/codegen/unchecked-float-casts.rs
@@ -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() }
 }
diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
index f13964fb386..811efaefbb5 100644
--- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
+++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
@@ -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)]