From ae23f7020a5cb9a201e83f20f151282368b1f494 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Feb 2020 15:48:18 +0100 Subject: [PATCH] const-prop: use overflowing_unary_op for overflowing checking of unary ops --- src/librustc_mir/transform/const_prop.rs | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d645f6cf183..d09165f904a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -518,18 +518,19 @@ fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Optio } } - 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); - - 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) - } + let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?; + let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; + + if overflow { + assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); + throw_panic!(OverflowNeg); } Ok(()) @@ -574,11 +575,10 @@ fn check_binary_op( 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 @@ fn const_prop( // 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 -- 2.44.0