[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