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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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