From: Richard Smith Date: Tue, 6 Nov 2012 02:30:30 +0000 (+0000) Subject: Classify the INT_MIN/-1 check as -fsanitize=signed-integer-overflow, not as -fsanitiz... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c54e25f9450d927dcd41270639523c1b4c0d5868;p=clang Classify the INT_MIN/-1 check as -fsanitize=signed-integer-overflow, not as -fsanitize=divide-by-zero. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167433 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index c21cbf6773..b429b1d6e4 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1924,30 +1924,38 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) { - llvm::IntegerType *Ty = cast(Zero->getType()); + llvm::Value *Cond = 0; + + if (CGF.getLangOpts().SanitizeDivideByZero) + Cond = Builder.CreateICmpNE(Ops.RHS, Zero); + + if (CGF.getLangOpts().SanitizeSignedIntegerOverflow && + Ops.Ty->hasSignedIntegerRepresentation()) { + llvm::IntegerType *Ty = cast(Zero->getType()); - if (Ops.Ty->hasSignedIntegerRepresentation()) { llvm::Value *IntMin = Builder.getInt(llvm::APInt::getSignedMinValue(Ty->getBitWidth())); llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL); - llvm::Value *Cond1 = Builder.CreateICmpNE(Ops.RHS, Zero); llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin); llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne); - llvm::Value *Cond2 = Builder.CreateOr(LHSCmp, RHSCmp, "or"); - EmitBinOpCheck(Builder.CreateAnd(Cond1, Cond2, "and"), Ops); - } else { - EmitBinOpCheck(Builder.CreateICmpNE(Ops.RHS, Zero), Ops); + llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or"); + Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow; } + + if (Cond) + EmitBinOpCheck(Cond, Ops); } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { - if (CGF.getLangOpts().SanitizeDivideByZero) { + if (CGF.getLangOpts().SanitizeDivideByZero || + CGF.getLangOpts().SanitizeSignedIntegerOverflow) { llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); if (Ops.Ty->isIntegerType()) EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); - else if (Ops.Ty->isRealFloatingType()) + else if (CGF.getLangOpts().SanitizeDivideByZero && + Ops.Ty->isRealFloatingType()) EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); } if (Ops.LHS->getType()->isFPOrFPVectorTy()) { diff --git a/test/CodeGen/catch-undef-behavior.c b/test/CodeGen/catch-undef-behavior.c index bc5ec63e1a..4198b62ea5 100644 --- a/test/CodeGen/catch-undef-behavior.c +++ b/test/CodeGen/catch-undef-behavior.c @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,divide-by-zero -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s // RUN: %clang_cc1 -fsanitize=null -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %clang_cc1 -fsanitize=signed-integer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-OVERFLOW // CHECK: @[[INT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" } @@ -221,3 +222,27 @@ float float_float_overflow(double f) { // CHECK: call void @__ubsan_handle_float_cast_overflow( return f; } + +// CHECK: @int_divide_overflow +// CHECK-OVERFLOW: @int_divide_overflow +int int_divide_overflow(int a, int b) { + // CHECK: %[[ZERO:.*]] = icmp ne i32 %[[B:.*]], 0 + // CHECK-OVERFLOW-NOT: icmp ne i32 %{{.*}}, 0 + + // CHECK: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 + // CHECK-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B]], -1 + // CHECK-NEXT: %[[OVER:.*]] = or i1 %[[AOK]], %[[BOK]] + + // CHECK-OVERFLOW: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 + // CHECK-OVERFLOW-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B:.*]], -1 + // CHECK-OVERFLOW-NEXT: %[[OK:.*]] = or i1 %[[AOK]], %[[BOK]] + + // CHECK: %[[OK:.*]] = and i1 %[[ZERO]], %[[OVER]] + + // CHECK: br i1 %[[OK]] + // CHECK-OVERFLOW: br i1 %[[OK]] + return a / b; + + // CHECK: } + // CHECK-OVERFLOW: } +}