File: shift-near-oflo.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (103 lines) | stat: -rw-r--r-- 3,397 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//@ 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);
}