Skip to content

Commit de757e8

Browse files
orlpUrgau
authored andcommitted
Ensure NaN references values go through function boundary for next_up/down.
1 parent 3241bbc commit de757e8

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

library/std/src/f32/tests.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,18 @@ fn test_next_up() {
308308
let smallest_normal = f32::from_bits(0x0080_0000);
309309

310310
// Check that NaNs roundtrip.
311+
// Because x87 can lose NaN bits when passed through a function, ensure the reference value
312+
// also passes through a function boundary.
313+
#[inline(never)]
314+
fn identity(x: f32) -> f32 {
315+
crate::hint::black_box(x)
316+
}
311317
let nan0 = f32::NAN;
312318
let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
313319
let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
314-
assert_eq!(nan0.next_up().to_bits(), nan0.to_bits());
315-
assert_eq!(nan1.next_up().to_bits(), nan1.to_bits());
316-
assert_eq!(nan2.next_up().to_bits(), nan2.to_bits());
320+
assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits());
321+
assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits());
322+
assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits());
317323

318324
assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN);
319325
assert_eq!(f32::MIN.next_up(), -max_down);
@@ -339,12 +345,18 @@ fn test_next_down() {
339345
let smallest_normal = f32::from_bits(0x0080_0000);
340346

341347
// Check that NaNs roundtrip.
348+
// Because x87 can lose NaN bits when passed through a function, ensure the reference value
349+
// also passes through a function boundary.
350+
#[inline(never)]
351+
fn identity(x: f32) -> f32 {
352+
crate::hint::black_box(x)
353+
}
342354
let nan0 = f32::NAN;
343355
let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
344356
let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
345-
assert_eq!(nan0.next_down().to_bits(), nan0.to_bits());
346-
assert_eq!(nan1.next_down().to_bits(), nan1.to_bits());
347-
assert_eq!(nan2.next_down().to_bits(), nan2.to_bits());
357+
assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits());
358+
assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits());
359+
assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits());
348360

349361
assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
350362
assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY);

library/std/src/f64/tests.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,18 @@ fn test_next_up() {
298298
let smallest_normal = f64::from_bits(0x0010_0000_0000_0000);
299299

300300
// Check that NaNs roundtrip.
301+
// Because x87 can lose NaN bits when passed through a function, ensure the reference value
302+
// also passes through a function boundary.
303+
#[inline(never)]
304+
fn identity(x: f64) -> f64 {
305+
crate::hint::black_box(x)
306+
}
301307
let nan0 = f64::NAN;
302308
let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa);
303309
let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555);
304-
assert_eq!(nan0.next_up().to_bits(), nan0.to_bits());
305-
assert_eq!(nan1.next_up().to_bits(), nan1.to_bits());
306-
assert_eq!(nan2.next_up().to_bits(), nan2.to_bits());
310+
assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits());
311+
assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits());
312+
assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits());
307313

308314
assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN);
309315
assert_eq!(f64::MIN.next_up(), -max_down);
@@ -329,12 +335,18 @@ fn test_next_down() {
329335
let smallest_normal = f64::from_bits(0x0010_0000_0000_0000);
330336

331337
// Check that NaNs roundtrip.
338+
// Because x87 can lose NaN bits when passed through a function, ensure the reference value
339+
// also passes through a function boundary.
340+
#[inline(never)]
341+
fn identity(x: f64) -> f64 {
342+
crate::hint::black_box(x)
343+
}
332344
let nan0 = f64::NAN;
333345
let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa);
334346
let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555);
335-
assert_eq!(nan0.next_down().to_bits(), nan0.to_bits());
336-
assert_eq!(nan1.next_down().to_bits(), nan1.to_bits());
337-
assert_eq!(nan2.next_down().to_bits(), nan2.to_bits());
347+
assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits());
348+
assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits());
349+
assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits());
338350

339351
assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
340352
assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY);

0 commit comments

Comments
 (0)