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
5unsigned long li, lj, lk;
6unsigned int ii, ij, ik;
7
8extern void opaquelong(unsigned long);
9extern void opaqueint(unsigned int);
10
11// CHECK-LABEL: define void @testlongadd()
12void 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()
24void 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()
36void 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()
48void 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()
59void 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()
70void 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()
82void 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()
94void 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()
106void 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()
117void 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