]> granicus.if.org Git - clang/commitdiff
Classify the INT_MIN/-1 check as -fsanitize=signed-integer-overflow, not as -fsanitiz...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 6 Nov 2012 02:30:30 +0000 (02:30 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 6 Nov 2012 02:30:30 +0000 (02:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167433 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprScalar.cpp
test/CodeGen/catch-undef-behavior.c

index c21cbf67731eaed51e091c14bf8de3e920104cc3..b429b1d6e47ed1c5760aefb06df5c8613d57d3c3 100644 (file)
@@ -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<llvm::IntegerType>(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<llvm::IntegerType>(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()) {
index bc5ec63e1ae3821cdef4d122fc2523473087d4d7..4198b62ea56cd766c10c90f243007574b056faec 100644 (file)
@@ -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: }
+}