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