[cfe-commits] r168701 - in /cfe/trunk: docs/UsersManual.html include/clang/Basic/Sanitizers.def lib/CodeGen/CGExprScalar.cpp lib/Driver/SanitizerArgs.h test/CodeGen/catch-undef-behavior.c test/CodeGen/unsigned-overflow.c test/CodeGen/unsigned-promotion.c test/CodeGen/unsigned-trapv.c test/CodeGenCXX/catch-undef-behavior.cpp test/Driver/fsanitize.c

Will Dietz wdietz2 at illinois.edu
Tue Nov 27 07:01:55 PST 2012


Author: wdietz2
Date: Tue Nov 27 09:01:55 2012
New Revision: 168701

URL: http://llvm.org/viewvc/llvm-project?rev=168701&view=rev
Log:
Add -fsanitize=integer for reporting suspicious integer behaviors.

Introduces new sanitizer "unsigned-integer-overflow".

Added:
    cfe/trunk/test/CodeGen/unsigned-overflow.c
    cfe/trunk/test/CodeGen/unsigned-promotion.c
    cfe/trunk/test/CodeGen/unsigned-trapv.c
Modified:
    cfe/trunk/docs/UsersManual.html
    cfe/trunk/include/clang/Basic/Sanitizers.def
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Driver/SanitizerArgs.h
    cfe/trunk/test/CodeGen/catch-undef-behavior.c
    cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp
    cfe/trunk/test/Driver/fsanitize.c

Modified: cfe/trunk/docs/UsersManual.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.html?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/docs/UsersManual.html (original)
+++ cfe/trunk/docs/UsersManual.html Tue Nov 27 09:01:55 2012
@@ -875,21 +875,27 @@
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <dl>
 <dt id="opt_fsanitize"><b>-fsanitize=check1,check2</b>: Turn on runtime checks
-for various forms of undefined behavior.</dt>
+for various forms of undefined or suspicious behavior.</dt>
 
 <dd>This option controls whether Clang adds runtime checks for various forms of
-undefined behavior, and is disabled by default. If a check fails, a diagnostic
-message is produced at runtime explaining the problem. The main checks are:
+undefined or suspicious behavior, and is disabled by default. If a check
+fails, a diagnostic message is produced at runtime explaining the problem. The
+main checks are:
 
 <ul>
 <li id="opt_fsanitize_address"><tt>-fsanitize=address</tt>:
     <a href="AddressSanitizer.html">AddressSanitizer</a>, a memory error
     detector.</li>
+<li id="opt_fsanitize_integer"><tt>-fsanitize=integer</tt>:
+    Enables checks for undefined or suspicious integer behavior.</li>
 <li id="opt_fsanitize_thread"><tt>-fsanitize=thread</tt>:
     <a href="ThreadSanitizer.html">ThreadSanitizer</a>, an <em>experimental</em>
     data race detector.  Not ready for widespread use.</li>
 <li id="opt_fsanitize_undefined"><tt>-fsanitize=undefined</tt>:
-    Enables all the checks listed below.</li>
+    Fast and compatible undefined behavior checker.  Enables the undefined behavior
+    checks that have small runtime cost and no impact on address space layout
+    or ABI.  This includes all of the checks listed below other than unsigned
+    integer overflow.</li>
 </ul>
 
 The following more fine-grained checks are also available:
@@ -897,11 +903,13 @@
 <ul>
 <li id="opt_fsanitize_alignment"><tt>-fsanitize=alignment</tt>:
     Use of a misaligned pointer or creation of a misaligned reference.</li>
-<li id="opt_fsanitize_divide-by-zero"><tt>-fsanitize=divide-by-zero</tt>:
-    Division by zero.</li>
 <li id="opt_fsanitize_float-cast-overflow"><tt>-fsanitize=float-cast-overflow</tt>:
     Conversion to, from, or between floating-point types which would overflow
     the destination.</li>
+<li id="opt_fsanitize_float-divide-by-zero"><tt>-fsanitize=float-divide-by-zero</tt>:
+    Floating point division by zero.</li>
+<li id="opt_fsanitize_integer-divide-by-zero"><tt>-fsanitize=integer-divide-by-zero</tt>:
+    Integer division by zero.</li>
 <li id="opt_fsanitize_null"><tt>-fsanitize=null</tt>:
     Use of a null pointer or creation of a null reference.</li>
 <li id="opt_fsanitize_object-size"><tt>-fsanitize=object-size</tt>:
@@ -923,6 +931,8 @@
     and checking for overflow in signed division (<tt>INT_MIN / -1</tt>).</li>
 <li id="opt_fsanitize_unreachable"><tt>-fsanitize=unreachable</tt>:
     If control flow reaches __builtin_unreachable.</li>
+<li id="opt_fsanitize_unsigned-integer-overflow"><tt>-fsanitize=unsigned-integer-overflow</tt>:
+    Unsigned integer overflows.</li>
 <li id="opt_fsanitize_vla-bound"><tt>-fsanitize=vla-bound</tt>:
     A variable-length array whose bound does not evaluate to a positive value.</li>
 <li id="opt_fsanitize_vptr"><tt>-fsanitize=vptr</tt>:

Modified: cfe/trunk/include/clang/Basic/Sanitizers.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Sanitizers.def (original)
+++ cfe/trunk/include/clang/Basic/Sanitizers.def Tue Nov 27 09:01:55 2012
@@ -45,26 +45,34 @@
 SANITIZER("thread", Thread)
 
 // UndefinedBehaviorSanitizer
-SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
-SANITIZER("divide-by-zero", DivideByZero)
+SANITIZER("alignment", Alignment)
+SANITIZER("bounds", Bounds)
+SANITIZER("float-cast-overflow", FloatCastOverflow)
+SANITIZER("float-divide-by-zero", FloatDivideByZero)
+SANITIZER("integer-divide-by-zero", IntegerDivideByZero)
+SANITIZER("null", Null)
+SANITIZER("object-size", ObjectSize)
+SANITIZER("return", Return)
 SANITIZER("shift", Shift)
+SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
 SANITIZER("unreachable", Unreachable)
-SANITIZER("return", Return)
 SANITIZER("vla-bound", VLABound)
-SANITIZER("alignment", Alignment)
-SANITIZER("null", Null)
 SANITIZER("vptr", Vptr)
-SANITIZER("object-size", ObjectSize)
-SANITIZER("float-cast-overflow", FloatCastOverflow)
-SANITIZER("bounds", Bounds)
+
+// IntegerSanitizer
+SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow)
 
 // -fsanitize=undefined (and its alias -fcatch-undefined-behavior). This should
 // include all the sanitizers which have low overhead, no ABI or address space
 // layout implications, and only catch undefined behavior.
 SANITIZER_GROUP("undefined", Undefined,
-                SignedIntegerOverflow | DivideByZero | Shift | Unreachable |
-                Return | VLABound | Alignment | Null | Vptr | ObjectSize |
-                FloatCastOverflow | Bounds)
+                Alignment | Bounds | FloatCastOverflow | FloatDivideByZero |
+                IntegerDivideByZero | Null | ObjectSize | Return | Shift |
+                SignedIntegerOverflow | Unreachable | VLABound | Vptr)
+
+SANITIZER_GROUP("integer", Integer,
+                SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
+                IntegerDivideByZero)
 
 #undef SANITIZER
 #undef SANITIZER_GROUP

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Nov 27 09:01:55 2012
@@ -414,6 +414,10 @@
       }
     }
 
+    if (Ops.Ty->isUnsignedIntegerType() &&
+        CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+      return EmitOverflowCheckedBinOp(Ops);
+
     if (Ops.LHS->getType()->isFPOrFPVectorTy())
       return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
     return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
@@ -1472,11 +1476,23 @@
 
     // 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.
-    if (type->isSignedIntegerOrEnumerationType() &&
-        value->getType()->getPrimitiveSizeInBits() >=
-            CGF.IntTy->getBitWidth())
+    if (value->getType()->getPrimitiveSizeInBits() >=
+            CGF.IntTy->getBitWidth() &&
+        type->isSignedIntegerOrEnumerationType()) {
       value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
-    else
+    } else if (value->getType()->getPrimitiveSizeInBits() >=
+               CGF.IntTy->getBitWidth() &&
+               type->isUnsignedIntegerType() &&
+               CGF.getLangOpts().SanitizeUnsignedIntegerOverflow) {
+      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 = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
   
   // Next most common: pointer increment.
@@ -1926,7 +1942,7 @@
     const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
   llvm::Value *Cond = 0;
 
-  if (CGF.getLangOpts().SanitizeDivideByZero)
+  if (CGF.getLangOpts().SanitizeIntegerDivideByZero)
     Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
 
   if (CGF.getLangOpts().SanitizeSignedIntegerOverflow &&
@@ -1948,16 +1964,17 @@
 }
 
 Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
-  if (CGF.getLangOpts().SanitizeDivideByZero ||
-      CGF.getLangOpts().SanitizeSignedIntegerOverflow) {
+  if ((CGF.getLangOpts().SanitizeIntegerDivideByZero ||
+      CGF.getLangOpts().SanitizeSignedIntegerOverflow) &&
+      Ops.Ty->isIntegerType()) {
     llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
-
-    if (Ops.Ty->isIntegerType())
-      EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
-    else if (CGF.getLangOpts().SanitizeDivideByZero &&
-             Ops.Ty->isRealFloatingType())
-      EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+    EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
+  } else if (CGF.getLangOpts().SanitizeFloatDivideByZero &&
+             Ops.Ty->isRealFloatingType()) {
+    llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
+    EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
   }
+
   if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
     llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
     if (CGF.getLangOpts().OpenCL) {
@@ -1978,10 +1995,10 @@
 
 Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
   // Rem in C can't be a floating point type: C99 6.5.5p2.
-  if (CGF.getLangOpts().SanitizeDivideByZero) {
+  if (CGF.getLangOpts().SanitizeIntegerDivideByZero) {
     llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
 
-    if (Ops.Ty->isIntegerType()) 
+    if (Ops.Ty->isIntegerType())
       EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false);
   }
 
@@ -1995,27 +2012,32 @@
   unsigned IID;
   unsigned OpID = 0;
 
+  bool isSigned = Ops.Ty->isSignedIntegerOrEnumerationType();
   switch (Ops.Opcode) {
   case BO_Add:
   case BO_AddAssign:
     OpID = 1;
-    IID = llvm::Intrinsic::sadd_with_overflow;
+    IID = isSigned ? llvm::Intrinsic::sadd_with_overflow :
+                     llvm::Intrinsic::uadd_with_overflow;
     break;
   case BO_Sub:
   case BO_SubAssign:
     OpID = 2;
-    IID = llvm::Intrinsic::ssub_with_overflow;
+    IID = isSigned ? llvm::Intrinsic::ssub_with_overflow :
+                     llvm::Intrinsic::usub_with_overflow;
     break;
   case BO_Mul:
   case BO_MulAssign:
     OpID = 3;
-    IID = llvm::Intrinsic::smul_with_overflow;
+    IID = isSigned ? llvm::Intrinsic::smul_with_overflow :
+                     llvm::Intrinsic::umul_with_overflow;
     break;
   default:
     llvm_unreachable("Unsupported operation for overflow detection");
   }
   OpID <<= 1;
-  OpID |= 1;
+  if (isSigned)
+    OpID |= 1;
 
   llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ops.Ty);
 
@@ -2031,7 +2053,7 @@
   if (handlerName->empty()) {
     // If the signed-integer-overflow sanitizer is enabled, emit a call to its
     // runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
-    if (CGF.getLangOpts().SanitizeSignedIntegerOverflow)
+    if (!isSigned || CGF.getLangOpts().SanitizeSignedIntegerOverflow)
       EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
     else
       CGF.EmitTrapvCheck(Builder.CreateNot(overflow));
@@ -2256,7 +2278,11 @@
       return EmitOverflowCheckedBinOp(op);
     }
   }
-    
+
+  if (op.Ty->isUnsignedIntegerType() &&
+      CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+    return EmitOverflowCheckedBinOp(op);
+
   if (op.LHS->getType()->isFPOrFPVectorTy()) {
     // Try to form an fmuladd.
     if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder))
@@ -2283,7 +2309,11 @@
         return EmitOverflowCheckedBinOp(op);
       }
     }
-    
+
+    if (op.Ty->isUnsignedIntegerType() &&
+        CGF.getLangOpts().SanitizeUnsignedIntegerOverflow)
+      return EmitOverflowCheckedBinOp(op);
+
     if (op.LHS->getType()->isFPOrFPVectorTy()) {
       // Try to form an fmuladd.
       if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true))

Modified: cfe/trunk/lib/Driver/SanitizerArgs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.h?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.h (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.h Tue Nov 27 09:01:55 2012
@@ -30,7 +30,7 @@
 #include "clang/Basic/Sanitizers.def"
     NeedsAsanRt = Address,
     NeedsTsanRt = Thread,
-    NeedsUbsanRt = Undefined ^ Bounds
+    NeedsUbsanRt = (Undefined & ~Bounds) | Integer
   };
   unsigned Kind;
 

Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original)
+++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Tue Nov 27 09:01:55 2012
@@ -1,4 +1,4 @@
-// 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=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-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
 

Added: cfe/trunk/test/CodeGen/unsigned-overflow.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/unsigned-overflow.c?rev=168701&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/unsigned-overflow.c (added)
+++ cfe/trunk/test/CodeGen/unsigned-overflow.c Tue Nov 27 09:01:55 2012
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s
+// Verify checked operations are emitted for integers and longs.
+// unsigned short/char's tested in unsigned-promotion.c
+
+unsigned long li, lj, lk;
+unsigned int ii, ij, ik;
+
+extern void opaquelong(unsigned long);
+extern void opaqueint(unsigned int);
+
+// CHECK: define void @testlongadd()
+void testlongadd() {
+
+  // CHECK:      [[T1:%.*]] = load i64* @lj
+  // CHECK-NEXT: [[T2:%.*]] = load i64* @lk
+  // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
+  // CHECK: call void @__ubsan_handle_add_overflow
+  li = lj + lk;
+}
+
+// CHECK: define void @testlongsub()
+void testlongsub() {
+
+  // CHECK:      [[T1:%.*]] = load i64* @lj
+  // CHECK-NEXT: [[T2:%.*]] = load i64* @lk
+  // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[T1]], i64 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
+  // CHECK: call void @__ubsan_handle_sub_overflow
+  li = lj - lk;
+}
+
+// CHECK: define void @testlongmul()
+void testlongmul() {
+
+  // CHECK:      [[T1:%.*]] = load i64* @lj
+  // CHECK-NEXT: [[T2:%.*]] = load i64* @lk
+  // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[T1]], i64 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
+  // CHECK: call void @__ubsan_handle_mul_overflow
+  li = lj * lk;
+}
+
+// CHECK: define void @testlongpostinc()
+void testlongpostinc() {
+  opaquelong(li++);
+
+  // CHECK:      [[T1:%.*]] = load i64* @li
+  // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1)
+  // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1
+  // CHECK:      call void @__ubsan_handle_add_overflow
+}
+
+// CHECK: define void @testlongpreinc()
+void testlongpreinc() {
+  opaquelong(++li);
+
+  // CHECK:      [[T1:%.*]] = load i64* @li
+  // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1)
+  // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1
+  // CHECK:      call void @__ubsan_handle_add_overflow
+}
+
+// CHECK: define void @testintadd()
+void testintadd() {
+
+  // CHECK:      [[T1:%.*]] = load i32* @ij
+  // CHECK-NEXT: [[T2:%.*]] = load i32* @ik
+  // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
+  // CHECK:      call void @__ubsan_handle_add_overflow
+  ii = ij + ik;
+}
+
+// CHECK: define void @testintsub()
+void testintsub() {
+
+  // CHECK:      [[T1:%.*]] = load i32* @ij
+  // CHECK-NEXT: [[T2:%.*]] = load i32* @ik
+  // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[T1]], i32 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
+  // CHECK:      call void @__ubsan_handle_sub_overflow
+  ii = ij - ik;
+}
+
+// CHECK: define void @testintmul()
+void testintmul() {
+
+  // CHECK:      [[T1:%.*]] = load i32* @ij
+  // CHECK-NEXT: [[T2:%.*]] = load i32* @ik
+  // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[T1]], i32 [[T2]])
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
+  // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
+  // CHECK:      call void @__ubsan_handle_mul_overflow
+  ii = ij * ik;
+}
+
+// CHECK: define void @testintpostinc()
+void testintpostinc() {
+  opaqueint(ii++);
+
+  // CHECK:      [[T1:%.*]] = load i32* @ii
+  // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1)
+  // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1
+  // CHECK:      call void @__ubsan_handle_add_overflow
+}
+
+// CHECK: define void @testintpreinc()
+void testintpreinc() {
+  opaqueint(++ii);
+
+  // CHECK:      [[T1:%.*]] = load i32* @ii
+  // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1)
+  // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
+  // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1
+  // CHECK:      call void @__ubsan_handle_add_overflow
+}

Added: cfe/trunk/test/CodeGen/unsigned-promotion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/unsigned-promotion.c?rev=168701&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/unsigned-promotion.c (added)
+++ cfe/trunk/test/CodeGen/unsigned-promotion.c Tue Nov 27 09:01:55 2012
@@ -0,0 +1,143 @@
+// Check -fsanitize=signed-integer-overflow and
+// -fsanitize=unsigned-integer-overflow with promoted unsigned types
+//
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \
+// RUN:   -fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKS
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \
+// RUN:   -fsanitize=unsigned-integer-overflow | FileCheck %s --check-prefix=CHECKU
+
+unsigned short si, sj, sk;
+unsigned char ci, cj, ck;
+
+extern void opaqueshort(unsigned short);
+extern void opaquechar(unsigned char);
+
+// CHECKS:   define void @testshortadd()
+// CHECKU: define void @testshortadd()
+void testshortadd() {
+  // CHECKS:        load i16* @sj
+  // CHECKS:        load i16* @sk
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_add_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i16* @sj
+  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i16* @sk
+  // CHECKU:      [[T4:%.*]] = zext i16 [[T3]]
+  // CHECKU-NOT:  llvm.sadd
+  // CHECKU-NOT:  llvm.uadd
+  // CHECKU:      [[T5:%.*]] = add nsw i32 [[T2]], [[T4]]
+
+  si = sj + sk;
+}
+
+// CHECKS:   define void @testshortsub()
+// CHECKU: define void @testshortsub()
+void testshortsub() {
+
+  // CHECKS:        load i16* @sj
+  // CHECKS:        load i16* @sk
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_sub_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i16* @sj
+  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i16* @sk
+  // CHECKU:      [[T4:%.*]] = zext i16 [[T3]]
+  // CHECKU-NOT:  llvm.ssub
+  // CHECKU-NOT:  llvm.usub
+  // CHECKU:      [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]]
+
+  si = sj - sk;
+}
+
+// CHECKS:   define void @testshortmul()
+// CHECKU: define void @testshortmul()
+void testshortmul() {
+
+  // CHECKS:        load i16* @sj
+  // CHECKS:        load i16* @sk
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_mul_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i16* @sj
+  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i16* @sk
+  // CHECKU:      [[T4:%.*]] = zext i16 [[T3]]
+  // CHECKU-NOT:  llvm.smul
+  // CHECKU-NOT:  llvm.umul
+  // CHECKU:      [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]]
+  si = sj * sk;
+}
+
+// CHECKS:   define void @testcharadd()
+// CHECKU: define void @testcharadd()
+void testcharadd() {
+
+  // CHECKS:        load i8* @cj
+  // CHECKS:        load i8* @ck
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_add_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i8* @cj
+  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i8* @ck
+  // CHECKU:      [[T4:%.*]] = zext i8 [[T3]]
+  // CHECKU-NOT:  llvm.sadd
+  // CHECKU-NOT:  llvm.uadd
+  // CHECKU:      [[T5:%.*]] = add nsw i32 [[T2]], [[T4]]
+
+  ci = cj + ck;
+}
+
+// CHECKS:   define void @testcharsub()
+// CHECKU: define void @testcharsub()
+void testcharsub() {
+
+  // CHECKS:        load i8* @cj
+  // CHECKS:        load i8* @ck
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_sub_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i8* @cj
+  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i8* @ck
+  // CHECKU:      [[T4:%.*]] = zext i8 [[T3]]
+  // CHECKU-NOT:  llvm.ssub
+  // CHECKU-NOT:  llvm.usub
+  // CHECKU:      [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]]
+
+  ci = cj - ck;
+}
+
+// CHECKS:   define void @testcharmul()
+// CHECKU: define void @testcharmul()
+void testcharmul() {
+
+  // CHECKS:        load i8* @cj
+  // CHECKS:        load i8* @ck
+  // CHECKS:        [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
+  // CHECKS-NEXT:   [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
+  // CHECKS-NEXT:   [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
+  // CHECKS:        call void @__ubsan_handle_mul_overflow
+  //
+  // CHECKU:      [[T1:%.*]] = load i8* @cj
+  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
+  // CHECKU:      [[T3:%.*]] = load i8* @ck
+  // CHECKU:      [[T4:%.*]] = zext i8 [[T3]]
+  // CHECKU-NOT:  llvm.smul
+  // CHECKU-NOT:  llvm.umul
+  // CHECKU:      [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]]
+
+  ci = cj * ck;
+}

Added: cfe/trunk/test/CodeGen/unsigned-trapv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/unsigned-trapv.c?rev=168701&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/unsigned-trapv.c (added)
+++ cfe/trunk/test/CodeGen/unsigned-trapv.c Tue Nov 27 09:01:55 2012
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=unsigned-integer-overflow | FileCheck %s --check-prefix=UNSIGNED
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=TRAPV
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=unsigned-integer-overflow -ftrapv | FileCheck %s --check-prefix=BOTH
+// Verify that -ftrapv and -fsanitize=unsigned-integer-overflow
+// work together as expected
+
+
+// UNSIGNED: @test_signed
+// TRAPV: @test_signed
+// BOTH: @test_signed
+void test_signed() {
+  extern volatile int a, b, c;
+  // UNSIGNED: add nsw i32
+  // UNSIGNED-NOT: overflow
+  // TRAPV: sadd.with.overflow.i32
+  // TRAPV-NOT: ubsan
+  // TRAPV: llvm.trap
+  // BOTH: sadd.with.overflow.i32
+  // BOTH-NOT: ubsan
+  // BOTH: llvm.trap
+  a = b + c;
+}
+
+// UNSIGNED: @test_unsigned
+// TRAPV: @test_unsigned
+// BOTH: @test_unsigned
+void test_unsigned() {
+  extern volatile unsigned x, y, z;
+  // UNSIGNED: uadd.with.overflow.i32
+  // UNSIGNED-NOT: llvm.trap
+  // UNSIGNED: ubsan
+  // TRAPV-NOT: overflow
+  // TRAPV-NOT: llvm.trap
+  // BOTH: uadd.with.overflow.i32
+  // BOTH: ubsan
+  // BOTH-NOT: llvm.trap
+  x = y + z;
+}

Modified: cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp Tue Nov 27 09:01:55 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsanitize=signed-integer-overflow,divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
 
 // CHECK: @_Z17reference_binding
 void reference_binding(int *p) {

Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=168701&r1=168700&r2=168701&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Tue Nov 27 09:01:55 2012
@@ -1,9 +1,14 @@
 // RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED
-// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|bounds),?){12}"}}
 
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
-// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|bounds),?){10}"}}
+// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|bounds),?){13}"}}
+//
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER
+// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift),?){4}"}}
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
+// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|bounds),?){11}"}}
 
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI





More information about the cfe-commits mailing list