diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 8cdb0e37f5507..48085c2145418 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -105,8 +105,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { | "overflowing_add" | "overflowing_sub" | "overflowing_mul" - | "unchecked_shl" - | "unchecked_shr" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { @@ -116,8 +114,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { "overflowing_add" => (BinOp::Add, true), "overflowing_sub" => (BinOp::Sub, true), "overflowing_mul" => (BinOp::Mul, true), - "unchecked_shl" => (BinOp::Shl, true), - "unchecked_shr" => (BinOp::Shr, true), "add_with_overflow" => (BinOp::Add, false), "sub_with_overflow" => (BinOp::Sub, false), "mul_with_overflow" => (BinOp::Mul, false), @@ -129,6 +125,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { self.binop_with_overflow(bin_op, lhs, rhs, dest)?; } } + "unchecked_shl" | "unchecked_shr" => { + let l = self.read_value(args[0])?; + let r = self.read_value(args[1])?; + let bin_op = match intrinsic_name { + "unchecked_shl" => BinOp::Shl, + "unchecked_shr" => BinOp::Shr, + _ => bug!("Already checked for int ops") + }; + let (val, overflowed) = self.binary_op_val(bin_op, l, r)?; + if overflowed { + let layout = self.layout_of(substs.type_at(0))?; + let r_val = r.to_scalar()?.to_bits(layout.size)?; + return err!(Intrinsic( + format!("Overflowing shift by {} in {}", r_val, intrinsic_name), + )); + } + self.write_scalar(val, dest)?; + } "transmute" => { // Go through an allocation, to make sure the completely different layouts // do not pose a problem. (When the user transmutes through a union, diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs new file mode 100644 index 0000000000000..cbf855633fd2d --- /dev/null +++ b/src/test/ui/consts/const-int-unchecked.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core_intrinsics)] + +use std::intrinsics; + +const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; +//^~ ERROR: Overflowing shift by 8 in unchecked_shr +const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; +//^~ ERROR: Overflowing shift by 8 in unchecked_shl + +fn main() { +} diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr new file mode 100644 index 0000000000000..b8fd0facbc1ae --- /dev/null +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -0,0 +1,20 @@ +error: this constant cannot be used + --> $DIR/const-int-unchecked.rs:15:1 + | +LL | const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^ + | | + | Overflowing shift by 8 in unchecked_shr + | + = note: #[deny(const_err)] on by default + +error: this constant cannot be used + --> $DIR/const-int-unchecked.rs:17:1 + | +LL | const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^ + | | + | Overflowing shift by 8 in unchecked_shl + +error: aborting due to 2 previous errors +