Home | History | Annotate | Download | only in CodeGen
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s
      2 // Verify checked operations are emitted for integers and longs.
      3 // unsigned short/char's tested in unsigned-promotion.c
      4 
      5 unsigned long li, lj, lk;
      6 unsigned int ii, ij, ik;
      7 
      8 extern void opaquelong(unsigned long);
      9 extern void opaqueint(unsigned int);
     10 
     11 // CHECK-LABEL: define void @testlongadd()
     12 void testlongadd() {
     13 
     14   // CHECK:      [[T1:%.*]] = load i64, i64* @lj
     15   // CHECK-NEXT: [[T2:%.*]] = load i64, i64* @lk
     16   // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 [[T2]])
     17   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
     18   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
     19   // CHECK: call void @__ubsan_handle_add_overflow
     20   li = lj + lk;
     21 }
     22 
     23 // CHECK-LABEL: define void @testlongsub()
     24 void testlongsub() {
     25 
     26   // CHECK:      [[T1:%.*]] = load i64, i64* @lj
     27   // CHECK-NEXT: [[T2:%.*]] = load i64, i64* @lk
     28   // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[T1]], i64 [[T2]])
     29   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
     30   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
     31   // CHECK: call void @__ubsan_handle_sub_overflow
     32   li = lj - lk;
     33 }
     34 
     35 // CHECK-LABEL: define void @testlongmul()
     36 void testlongmul() {
     37 
     38   // CHECK:      [[T1:%.*]] = load i64, i64* @lj
     39   // CHECK-NEXT: [[T2:%.*]] = load i64, i64* @lk
     40   // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[T1]], i64 [[T2]])
     41   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0
     42   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1
     43   // CHECK: call void @__ubsan_handle_mul_overflow
     44   li = lj * lk;
     45 }
     46 
     47 // CHECK-LABEL: define void @testlongpostinc()
     48 void testlongpostinc() {
     49   opaquelong(li++);
     50 
     51   // CHECK:      [[T1:%.*]] = load i64, i64* @li
     52   // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1)
     53   // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0
     54   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1
     55   // CHECK:      call void @__ubsan_handle_add_overflow
     56 }
     57 
     58 // CHECK-LABEL: define void @testlongpreinc()
     59 void testlongpreinc() {
     60   opaquelong(++li);
     61 
     62   // CHECK:      [[T1:%.*]] = load i64, i64* @li
     63   // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1)
     64   // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0
     65   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1
     66   // CHECK:      call void @__ubsan_handle_add_overflow
     67 }
     68 
     69 // CHECK-LABEL: define void @testintadd()
     70 void testintadd() {
     71 
     72   // CHECK:      [[T1:%.*]] = load i32, i32* @ij
     73   // CHECK-NEXT: [[T2:%.*]] = load i32, i32* @ik
     74   // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 [[T2]])
     75   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
     76   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
     77   // CHECK:      call void @__ubsan_handle_add_overflow
     78   ii = ij + ik;
     79 }
     80 
     81 // CHECK-LABEL: define void @testintsub()
     82 void testintsub() {
     83 
     84   // CHECK:      [[T1:%.*]] = load i32, i32* @ij
     85   // CHECK-NEXT: [[T2:%.*]] = load i32, i32* @ik
     86   // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[T1]], i32 [[T2]])
     87   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
     88   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
     89   // CHECK:      call void @__ubsan_handle_sub_overflow
     90   ii = ij - ik;
     91 }
     92 
     93 // CHECK-LABEL: define void @testintmul()
     94 void testintmul() {
     95 
     96   // CHECK:      [[T1:%.*]] = load i32, i32* @ij
     97   // CHECK-NEXT: [[T2:%.*]] = load i32, i32* @ik
     98   // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[T1]], i32 [[T2]])
     99   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0
    100   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1
    101   // CHECK:      call void @__ubsan_handle_mul_overflow
    102   ii = ij * ik;
    103 }
    104 
    105 // CHECK-LABEL: define void @testintpostinc()
    106 void testintpostinc() {
    107   opaqueint(ii++);
    108 
    109   // CHECK:      [[T1:%.*]] = load i32, i32* @ii
    110   // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1)
    111   // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
    112   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1
    113   // CHECK:      call void @__ubsan_handle_add_overflow
    114 }
    115 
    116 // CHECK-LABEL: define void @testintpreinc()
    117 void testintpreinc() {
    118   opaqueint(++ii);
    119 
    120   // CHECK:      [[T1:%.*]] = load i32, i32* @ii
    121   // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1)
    122   // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
    123   // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1
    124   // CHECK:      call void @__ubsan_handle_add_overflow
    125 }
    126