// 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-LABEL: define{{.*}} void @testlongadd() void testlongadd() { // CHECK: [[T1:%.*]] = load i64, i64* @lj // CHECK-NEXT: [[T2:%.*]] = load i64, 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-LABEL: define{{.*}} void @testlongsub() void testlongsub() { // CHECK: [[T1:%.*]] = load i64, i64* @lj // CHECK-NEXT: [[T2:%.*]] = load i64, 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-LABEL: define{{.*}} void @testlongmul() void testlongmul() { // CHECK: [[T1:%.*]] = load i64, i64* @lj // CHECK-NEXT: [[T2:%.*]] = load i64, 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-LABEL: define{{.*}} void @testlongpostinc() void testlongpostinc() { opaquelong(li++); // CHECK: [[T1:%.*]] = load i64, 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-LABEL: define{{.*}} void @testlongpreinc() void testlongpreinc() { opaquelong(++li); // CHECK: [[T1:%.*]] = load i64, 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-LABEL: define{{.*}} void @testintadd() void testintadd() { // CHECK: [[T1:%.*]] = load i32, i32* @ij // CHECK-NEXT: [[T2:%.*]] = load i32, 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-LABEL: define{{.*}} void @testintsub() void testintsub() { // CHECK: [[T1:%.*]] = load i32, i32* @ij // CHECK-NEXT: [[T2:%.*]] = load i32, 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-LABEL: define{{.*}} void @testintmul() void testintmul() { // CHECK: [[T1:%.*]] = load i32, i32* @ij // CHECK-NEXT: [[T2:%.*]] = load i32, 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-LABEL: define{{.*}} void @testintpostinc() void testintpostinc() { opaqueint(ii++); // CHECK: [[T1:%.*]] = load i32, 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-LABEL: define{{.*}} void @testintpreinc() void testintpreinc() { opaqueint(++ii); // CHECK: [[T1:%.*]] = load i32, 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 }