|
14 | 14 |
|
15 | 15 | use rustc::hir::def::Def;
|
16 | 16 | use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
|
17 |
| -use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind}; |
| 17 | +use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind}; |
18 | 18 | use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
19 | 19 | use rustc::mir::visit::{Visitor, PlaceContext};
|
20 | 20 | use rustc::mir::interpret::{
|
@@ -381,6 +381,20 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
381 | 381 | let (arg, _) = self.eval_operand(arg, source_info)?;
|
382 | 382 | let val = self.use_ecx(source_info, |this| {
|
383 | 383 | let prim = this.ecx.read_scalar(arg)?.not_undef()?;
|
| 384 | + match op { |
| 385 | + UnOp::Neg => { |
| 386 | + // Need to do overflow check here: For actual CTFE, MIR |
| 387 | + // generation emits code that does this before calling the op. |
| 388 | + let size = arg.layout.size; |
| 389 | + if prim.to_bits(size)? == (1 << (size.bits() - 1)) { |
| 390 | + return err!(OverflowNeg); |
| 391 | + } |
| 392 | + } |
| 393 | + UnOp::Not => { |
| 394 | + // Cannot overflow |
| 395 | + } |
| 396 | + } |
| 397 | + // Now run the actual operation. |
384 | 398 | this.ecx.unary_op(op, prim, arg.layout)
|
385 | 399 | })?;
|
386 | 400 | Some((OpTy::from_scalar_value(val, place_layout), span))
|
|
0 commit comments