blob: 458c1b121664e8929afaf3e0c3ffb7b02bba2b38 [file] [edit]
//! Verify the behavior differences between enabling and disabling overflow checks.
//@ run-pass
//@ needs-unwind
//@ revisions: ERROR WRAP
//@[ERROR] compile-flags: -C overflow-checks=true
//@[WRAP] compile-flags: -C overflow-checks=false
#![feature(cfg_overflow_checks)]
#![feature(funnel_shifts)]
use std::hint::black_box as bb;
use std::{assert_matches, fmt, panic};
#[track_caller]
fn check<T: fmt::Debug + PartialEq>(func: fn() -> T, wrapping_res: T, name: &str) {
let type_name = std::any::type_name::<T>();
let res = panic::catch_unwind(func);
if cfg!(overflow_checks) {
assert_matches!(res, Err(_), "{type_name} {name}");
} else {
assert_eq!(res.unwrap(), wrapping_res, "{type_name} {name}");
}
}
fn main() {
check(|| bb(u32::MAX) + bb(1), 0, "add");
check(|| bb(0u32) - bb(1), u32::MAX, "sub");
check(|| bb(u32::MAX) * bb(2), u32::MAX << 1, "mul");
check(|| bb(1u32) << bb(32), 1, "shl");
check(|| bb(u32::MAX) >> bb(32), u32::MAX, "shr");
check(|| bb(1234u32).funnel_shl(4567, bb(32)), 1234, "funnel_shl");
check(|| bb(1234u32).funnel_shr(4567, bb(32)), 4567, "funnel_shr");
check(|| bb(u32::MAX).pow(bb(2)), 1, "pow");
check(|| bb(u32::MAX).next_power_of_two(), 0, "next_power_of_two");
check(|| bb(i32::MAX) + bb(1), i32::MIN, "add");
check(|| bb(i32::MIN) - bb(1), i32::MAX, "sub");
check(|| bb(i32::MAX) * bb(2), i32::MAX << 1, "mul");
check(|| -bb(i32::MIN), i32::MIN, "neg");
check(|| bb(i32::MIN).abs(), i32::MIN, "abs");
check(|| bb(1) << bb(32), 1, "shl");
check(|| bb(i32::MAX) >> bb(32), i32::MAX, "shr");
check(|| bb(i32::MAX).pow(bb(2)), 1, "pow");
}