104 lines
3.3 KiB
Rust
104 lines
3.3 KiB
Rust
//@ run-pass
|
|
//@ compile-flags: -C debug-assertions
|
|
|
|
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
|
#![allow(static_mut_refs)]
|
|
|
|
// Check that we do *not* overflow on a number of edge cases.
|
|
// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
|
|
|
|
fn main() {
|
|
test_left_shift();
|
|
test_right_shift();
|
|
}
|
|
|
|
pub static mut HACK: i32 = 0;
|
|
|
|
// Work around constant-evaluation
|
|
// The point of this test is to exercise the code generated for execution at runtime,
|
|
// `id` can never be flagged as a const fn by future aggressive analyses...
|
|
// due to the modification of the static
|
|
#[inline(never)]
|
|
fn id<T>(x: T) -> T {
|
|
unsafe { HACK += 1; }
|
|
x
|
|
}
|
|
|
|
fn test_left_shift() {
|
|
// negative rhs can panic, but values in [0,N-1] are okay for iN
|
|
|
|
macro_rules! tests {
|
|
($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { {
|
|
let x = (1 as $iN) << id(0);
|
|
assert_eq!(x, 1);
|
|
let x = (1 as $uN) << id(0);
|
|
assert_eq!(x, 1);
|
|
let x = (1 as $iN) << id($max_rhs);
|
|
assert_eq!(x, $expect_i);
|
|
let x = (1 as $uN) << id($max_rhs);
|
|
assert_eq!(x, $expect_u);
|
|
// high-order bits on LHS are silently discarded without panic.
|
|
let x = (3 as $iN) << id($max_rhs);
|
|
assert_eq!(x, $expect_i);
|
|
let x = (3 as $uN) << id($max_rhs);
|
|
assert_eq!(x, $expect_u);
|
|
} }
|
|
}
|
|
|
|
let x = 1_i8 << id(0);
|
|
assert_eq!(x, 1);
|
|
let x = 1_u8 << id(0);
|
|
assert_eq!(x, 1);
|
|
let x = 1_i8 << id(7);
|
|
assert_eq!(x, i8::MIN);
|
|
let x = 1_u8 << id(7);
|
|
assert_eq!(x, 0x80);
|
|
// high-order bits on LHS are silently discarded without panic.
|
|
let x = 3_i8 << id(7);
|
|
assert_eq!(x, i8::MIN);
|
|
let x = 3_u8 << id(7);
|
|
assert_eq!(x, 0x80);
|
|
|
|
// above is (approximately) expanded from:
|
|
tests!(i8, u8, 7, i8::MIN, 0x80_u8);
|
|
|
|
tests!(i16, u16, 15, i16::MIN, 0x8000_u16);
|
|
tests!(i32, u32, 31, i32::MIN, 0x8000_0000_u32);
|
|
tests!(i64, u64, 63, i64::MIN, 0x8000_0000_0000_0000_u64);
|
|
}
|
|
|
|
fn test_right_shift() {
|
|
// negative rhs can panic, but values in [0,N-1] are okay for iN
|
|
|
|
macro_rules! tests {
|
|
($iN:ty, $uN:ty, $max_rhs:expr,
|
|
$signbit_i:expr, $highbit_i:expr, $highbit_u:expr) =>
|
|
{ {
|
|
let x = (1 as $iN) >> id(0);
|
|
assert_eq!(x, 1);
|
|
let x = (1 as $uN) >> id(0);
|
|
assert_eq!(x, 1);
|
|
let x = ($highbit_i) >> id($max_rhs-1);
|
|
assert_eq!(x, 1);
|
|
let x = ($highbit_u) >> id($max_rhs);
|
|
assert_eq!(x, 1);
|
|
// sign-bit is carried by arithmetic right shift
|
|
let x = ($signbit_i) >> id($max_rhs);
|
|
assert_eq!(x, -1);
|
|
// low-order bits on LHS are silently discarded without panic.
|
|
let x = ($highbit_i + 1) >> id($max_rhs-1);
|
|
assert_eq!(x, 1);
|
|
let x = ($highbit_u + 1) >> id($max_rhs);
|
|
assert_eq!(x, 1);
|
|
let x = ($signbit_i + 1) >> id($max_rhs);
|
|
assert_eq!(x, -1);
|
|
} }
|
|
}
|
|
|
|
tests!(i8, u8, 7, i8::MIN, 0x40_i8, 0x80_u8);
|
|
tests!(i16, u16, 15, i16::MIN, 0x4000_u16, 0x8000_u16);
|
|
tests!(i32, u32, 31, i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32);
|
|
tests!(i64, u64, 63, i64::MIN,
|
|
0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64);
|
|
}
|