Unify the way we report overflow in increment/decrement operator.
Summary: Make sure signed overflow in "x--" is checked with llvm.ssub.with.overflow intrinsic and is reported as: "-2147483648 - 1 cannot be represented in type 'int'" instead of: "-2147483648 + -1 cannot be represented in type 'int'" , like we do for unsigned overflow. Test Plan: clang + compiler-rt regression test suite Reviewers: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D8236 llvm-svn: 235568
This commit is contained in:
parent
434984ef58
commit
f624650354
|
@ -349,10 +349,9 @@ public:
|
|||
return EmitScalarPrePostIncDec(E, LV, true, true);
|
||||
}
|
||||
|
||||
llvm::Value *EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
|
||||
llvm::Value *InVal,
|
||||
llvm::Value *NextVal,
|
||||
bool IsInc);
|
||||
llvm::Value *EmitIncDecConsiderOverflowBehavior(const UnaryOperator *E,
|
||||
llvm::Value *InVal,
|
||||
bool IsInc);
|
||||
|
||||
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre);
|
||||
|
@ -1610,26 +1609,32 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
|
|||
// Unary Operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
llvm::Value *ScalarExprEmitter::
|
||||
EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
|
||||
llvm::Value *InVal,
|
||||
llvm::Value *NextVal, bool IsInc) {
|
||||
static BinOpInfo createBinOpInfoFromIncDec(const UnaryOperator *E,
|
||||
llvm::Value *InVal, bool IsInc) {
|
||||
BinOpInfo BinOp;
|
||||
BinOp.LHS = InVal;
|
||||
BinOp.RHS = llvm::ConstantInt::get(InVal->getType(), 1, false);
|
||||
BinOp.Ty = E->getType();
|
||||
BinOp.Opcode = IsInc ? BO_Add : BO_Sub;
|
||||
BinOp.FPContractable = false;
|
||||
BinOp.E = E;
|
||||
return BinOp;
|
||||
}
|
||||
|
||||
llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
|
||||
const UnaryOperator *E, llvm::Value *InVal, bool IsInc) {
|
||||
llvm::Value *Amount =
|
||||
llvm::ConstantInt::get(InVal->getType(), IsInc ? 1 : -1, true);
|
||||
StringRef Name = IsInc ? "inc" : "dec";
|
||||
switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
|
||||
case LangOptions::SOB_Defined:
|
||||
return Builder.CreateAdd(InVal, NextVal, IsInc ? "inc" : "dec");
|
||||
return Builder.CreateAdd(InVal, Amount, Name);
|
||||
case LangOptions::SOB_Undefined:
|
||||
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
|
||||
return Builder.CreateNSWAdd(InVal, NextVal, IsInc ? "inc" : "dec");
|
||||
return Builder.CreateNSWAdd(InVal, Amount, Name);
|
||||
// Fall through.
|
||||
case LangOptions::SOB_Trapping:
|
||||
BinOpInfo BinOp;
|
||||
BinOp.LHS = InVal;
|
||||
BinOp.RHS = NextVal;
|
||||
BinOp.Ty = E->getType();
|
||||
BinOp.Opcode = BO_Add;
|
||||
BinOp.FPContractable = false;
|
||||
BinOp.E = E;
|
||||
return EmitOverflowCheckedBinOp(BinOp);
|
||||
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc));
|
||||
}
|
||||
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
|
||||
}
|
||||
|
@ -1707,27 +1712,20 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||
|
||||
// Most common case by far: integer increment.
|
||||
} else if (type->isIntegerType()) {
|
||||
|
||||
llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
|
||||
|
||||
// Note that signed integer inc/dec with width less than int can't
|
||||
// overflow because of promotion rules; we're just eliding a few steps here.
|
||||
bool CanOverflow = value->getType()->getIntegerBitWidth() >=
|
||||
CGF.IntTy->getIntegerBitWidth();
|
||||
if (CanOverflow && type->isSignedIntegerOrEnumerationType()) {
|
||||
value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
|
||||
value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
|
||||
} else if (CanOverflow && type->isUnsignedIntegerType() &&
|
||||
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
|
||||
BinOpInfo BinOp;
|
||||
BinOp.LHS = value;
|
||||
BinOp.RHS = llvm::ConstantInt::get(value->getType(), 1, false);
|
||||
BinOp.Ty = E->getType();
|
||||
BinOp.Opcode = isInc ? BO_Add : BO_Sub;
|
||||
BinOp.FPContractable = false;
|
||||
BinOp.E = E;
|
||||
value = EmitOverflowCheckedBinOp(BinOp);
|
||||
} else
|
||||
value =
|
||||
EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc));
|
||||
} else {
|
||||
llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
|
||||
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
|
||||
}
|
||||
|
||||
// Next most common: pointer increment.
|
||||
} else if (const PointerType *ptr = type->getAs<PointerType>()) {
|
||||
|
|
|
@ -52,8 +52,8 @@ void test1() {
|
|||
|
||||
// DEFAULT: add nsw i32 {{.*}}, -1
|
||||
// WRAPV: add i32 {{.*}}, -1
|
||||
// TRAPV: llvm.sadd.with.overflow.i32({{.*}}, i32 -1)
|
||||
// CATCH_UB: llvm.sadd.with.overflow.i32({{.*}}, i32 -1)
|
||||
// TRAPV: llvm.ssub.with.overflow.i32({{.*}}, i32 1)
|
||||
// CATCH_UB: llvm.ssub.with.overflow.i32({{.*}}, i32 1)
|
||||
// TRAPV_HANDLER: foo(
|
||||
--a;
|
||||
|
||||
|
|
Loading…
Reference in New Issue