const-prop: use overflowing_unary_op for overflowing checking of unary ops

This commit is contained in:
Ralf Jung 2020-02-09 15:48:18 +01:00
parent 7d2f6ae001
commit ae23f7020a

View File

@ -518,18 +518,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
}
fn check_unary_op(&mut self, arg: &Operand<'tcx>, source_info: SourceInfo) -> Option<()> {
fn check_unary_op(
&mut self,
op: UnOp,
arg: &Operand<'tcx>,
source_info: SourceInfo,
) -> Option<()> {
self.use_ecx(source_info, |this| {
let ty = arg.ty(&this.local_decls, this.tcx);
let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?;
let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?;
if ty.is_integral() {
let arg = this.ecx.eval_operand(arg, None)?;
let prim = this.ecx.read_immediate(arg)?;
// Need to do overflow check here: For actual CTFE, MIR
// generation emits code that does this before calling the op.
if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
throw_panic!(OverflowNeg)
}
if overflow {
assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
throw_panic!(OverflowNeg);
}
Ok(())
@ -574,11 +575,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if !overflow_check {
self.use_ecx(source_info, |this| {
let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
let (_, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
if overflow {
let err = err_panic!(Overflow(op)).into();
return Err(err);
throw_panic!(Overflow(op));
}
Ok(())
@ -618,9 +618,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// Additional checking: if overflow checks are disabled (which is usually the case in
// release mode), then we need to do additional checking here to give lints to the user
// if an overflow would occur.
Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => {
trace!("checking UnaryOp(op = Neg, arg = {:?})", arg);
self.check_unary_op(arg, source_info)?;
Rvalue::UnaryOp(op, arg) if !overflow_check => {
trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
self.check_unary_op(*op, arg, source_info)?;
}
// Additional checking: check for overflows on integer binary operations and report