Skip to content

Commit 61ff823

Browse files
committed
Test suite for overflowing shift operators.
Note the tests have been revised to match new semantics for 8- and 16-bit values.
1 parent 19fef72 commit 61ff823

9 files changed

+280
-0
lines changed
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = 1_i32 << id(32);
19+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = 1 << id(-1);
19+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = 1_u64 << id(64);
19+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// This function is checking that our automatic truncation does not
15+
// sidestep the overflow checking.
16+
17+
// (Work around constant-evaluation)
18+
fn id<T>(x: T) -> T { x }
19+
20+
fn main() {
21+
let x = 1_i8 << id(17); // signals overflow when checking is on
22+
23+
// ... but when checking is off, the fallback will truncate the
24+
// input to its lower three bits (= 1). Note that this is *not*
25+
// the behavior of the x86 processor for 8- and 16-bit types,
26+
// but it is necessary to avoid undefined behavior from LLVM.
27+
//
28+
// We check that here, by ensuring the result has only been
29+
// shifted by one place; if overflow checking is turned off, then
30+
// this assertion will pass (and the compiletest driver will
31+
// report that the test did not produce the error expected above).
32+
assert_eq!(x, 2_i8);
33+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = -1_i32 >> id(32);
19+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = -1_i32 >> id(-1);
19+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// (Work around constant-evaluation)
15+
fn id<T>(x: T) -> T { x }
16+
17+
fn main() {
18+
let _x = -1_i64 >> id(64);
19+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
12+
// compile-flags: -C debug-assertions
13+
14+
// This function is checking that our (type-based) automatic
15+
// truncation does not sidestep the overflow checking.
16+
17+
// (Work around constant-evaluation)
18+
fn id<T>(x: T) -> T { x }
19+
20+
fn main() {
21+
let x = 2_i8 >> id(17); // signals overflow when checking is on
22+
23+
// ... but when checking is off, the fallback will truncate the
24+
// input to its lower three bits (= 1). Note that this is *not*
25+
// the behavior of the x86 processor for 8- and 16-bit types,
26+
// but it is necessary to avoid undefined behavior from LLVM.
27+
//
28+
// We check that here, by ensuring the result is not zero; if
29+
// overflow checking is turned off, then this assertion will pass
30+
// (and the compiletest driver will report that the test did not
31+
// produce the error expected above).
32+
assert_eq!(x, 1_i8);
33+
}

src/test/run-pass/shift-near-oflo.rs

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -C debug-assertions
12+
13+
// Check that we do *not* overflow on a number of edge cases.
14+
// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
15+
16+
// (Work around constant-evaluation)
17+
fn id<T>(x: T) -> T { x }
18+
19+
fn main() {
20+
test_left_shift();
21+
test_right_shift();
22+
}
23+
24+
fn test_left_shift() {
25+
// negative rhs can panic, but values in [0,N-1] are okay for iN
26+
27+
macro_rules! tests {
28+
($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { {
29+
let x = 1 as $iN << id(0);
30+
assert_eq!(x, 1);
31+
let x = 1 as $uN << id(0);
32+
assert_eq!(x, 1);
33+
let x = 1 as $iN << id($max_rhs);
34+
assert_eq!(x, $expect_i);
35+
let x = 1 as $uN << id($max_rhs);
36+
assert_eq!(x, $expect_u);
37+
// high-order bits on LHS are silently discarded without panic.
38+
let x = 3 as $iN << id($max_rhs);
39+
assert_eq!(x, $expect_i);
40+
let x = 3 as $uN << id($max_rhs);
41+
assert_eq!(x, $expect_u);
42+
} }
43+
}
44+
45+
let x = 1_i8 << id(0);
46+
assert_eq!(x, 1);
47+
let x = 1_u8 << id(0);
48+
assert_eq!(x, 1);
49+
let x = 1_i8 << id(7);
50+
assert_eq!(x, std::i8::MIN);
51+
let x = 1_u8 << id(7);
52+
assert_eq!(x, 0x80);
53+
// high-order bits on LHS are silently discarded without panic.
54+
let x = 3_i8 << id(7);
55+
assert_eq!(x, std::i8::MIN);
56+
let x = 3_u8 << id(7);
57+
assert_eq!(x, 0x80);
58+
59+
// above is (approximately) expanded from:
60+
tests!(i8, u8, 7, std::i8::MIN, 0x80_u8);
61+
62+
tests!(i16, u16, 15, std::i16::MIN, 0x8000_u16);
63+
tests!(i32, u32, 31, std::i32::MIN, 0x8000_0000_u32);
64+
tests!(i64, u64, 63, std::i64::MIN, 0x8000_0000_0000_0000_u64);
65+
}
66+
67+
fn test_right_shift() {
68+
// negative rhs can panic, but values in [0,N-1] are okay for iN
69+
70+
macro_rules! tests {
71+
($iN:ty, $uN:ty, $max_rhs:expr,
72+
$signbit_i:expr, $highbit_i:expr, $highbit_u:expr) =>
73+
{ {
74+
let x = 1 as $iN >> id(0);
75+
assert_eq!(x, 1);
76+
let x = 1 as $uN >> id(0);
77+
assert_eq!(x, 1);
78+
let x = $highbit_i >> id($max_rhs-1);
79+
assert_eq!(x, 1);
80+
let x = $highbit_u >> id($max_rhs);
81+
assert_eq!(x, 1);
82+
// sign-bit is carried by arithmetic right shift
83+
let x = $signbit_i >> id($max_rhs);
84+
assert_eq!(x, -1);
85+
// low-order bits on LHS are silently discarded without panic.
86+
let x = $highbit_i + 1 >> id($max_rhs-1);
87+
assert_eq!(x, 1);
88+
let x = $highbit_u + 1 >> id($max_rhs);
89+
assert_eq!(x, 1);
90+
let x = $signbit_i + 1 >> id($max_rhs);
91+
assert_eq!(x, -1);
92+
} }
93+
}
94+
95+
tests!(i8, u8, 7, std::i8::MIN, 0x40_i8, 0x80_u8);
96+
tests!(i16, u16, 15, std::i16::MIN, 0x4000_u16, 0x8000_u16);
97+
tests!(i32, u32, 31, std::i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32);
98+
tests!(i64, u64, 63, std::i64::MIN,
99+
0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64);
100+
}

0 commit comments

Comments
 (0)