Skip to content

Commit c34fa8b

Browse files
committed
Add conditional overflow-checking to signed negate operator.
1 parent 9a6d7fb commit c34fa8b

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/librustc_trans/trans/expr.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -1530,11 +1530,26 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
15301530
ast::UnNeg => {
15311531
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
15321532
let val = datum.to_llscalarish(bcx);
1533-
let llneg = {
1533+
let (bcx, llneg) = {
15341534
if ty::type_is_fp(un_ty) {
1535-
FNeg(bcx, val, debug_loc)
1535+
let result = FNeg(bcx, val, debug_loc);
1536+
(bcx, result)
15361537
} else {
1537-
Neg(bcx, val, debug_loc)
1538+
let is_signed = ty::type_is_signed(un_ty);
1539+
let result = Neg(bcx, val, debug_loc);
1540+
let bcx = if bcx.ccx().check_overflow() && is_signed {
1541+
let (llty, min) = base::llty_and_min_for_signed_ty(bcx, un_ty);
1542+
let is_min = ICmp(bcx, llvm::IntEQ, val,
1543+
C_integral(llty, min, true), debug_loc);
1544+
with_cond(bcx, is_min, |bcx| {
1545+
let msg = InternedString::new(
1546+
"attempted to negate with overflow");
1547+
controlflow::trans_fail(bcx, expr_info(expr), msg)
1548+
})
1549+
} else {
1550+
bcx
1551+
};
1552+
(bcx, result)
15381553
}
15391554
};
15401555
immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()

0 commit comments

Comments
 (0)