blob: c8d828dd33e7a7779511be28e888edf13577f82e [file] [log] [blame]
Michael Gottesman930ecdb2013-06-20 23:28:10 +00001// Test CodeGen for Security Check Overflow Builtins.
2// rdar://13421498
3
Rafael Espindolaff7cea82013-09-04 04:12:25 +00004// RUN: %clang_cc1 -triple "i686-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
5// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
6// RUN: %clang_cc1 -triple "x86_64-mingw32" -emit-llvm -x c %s -o - | FileCheck %s
Michael Gottesman930ecdb2013-06-20 23:28:10 +00007
8extern unsigned UnsignedErrorCode;
9extern unsigned long UnsignedLongErrorCode;
10extern unsigned long long UnsignedLongLongErrorCode;
11extern int IntErrorCode;
12extern long LongErrorCode;
13extern long long LongLongErrorCode;
John McCall03107a42015-10-29 20:48:01 +000014void overflowed(void);
15
16unsigned test_add_overflow_uint_uint_uint(unsigned x, unsigned y) {
17 // CHECK-LABEL: define i32 @test_add_overflow_uint_uint_uint
18 // CHECK-NOT: ext
19 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
20 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
21 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
22 // CHECK: store i32 [[Q]], i32*
23 // CHECK: br i1 [[C]]
24 unsigned r;
25 if (__builtin_add_overflow(x, y, &r))
26 overflowed();
27 return r;
28}
29
30int test_add_overflow_int_int_int(int x, int y) {
31 // CHECK-LABEL: define i32 @test_add_overflow_int_int_int
32 // CHECK-NOT: ext
33 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
34 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
35 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
36 // CHECK: store i32 [[Q]], i32*
37 // CHECK: br i1 [[C]]
38 int r;
39 if (__builtin_add_overflow(x, y, &r))
40 overflowed();
41 return r;
42}
43
44unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
45 // CHECK-LABEL: define i32 @test_sub_overflow_uint_uint_uint
46 // CHECK-NOT: ext
47 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
48 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
49 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
50 // CHECK: store i32 [[Q]], i32*
51 // CHECK: br i1 [[C]]
52 unsigned r;
53 if (__builtin_sub_overflow(x, y, &r))
54 overflowed();
55 return r;
56}
57
58int test_sub_overflow_int_int_int(int x, int y) {
59 // CHECK-LABEL: define i32 @test_sub_overflow_int_int_int
60 // CHECK-NOT: ext
61 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
62 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
63 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
64 // CHECK: store i32 [[Q]], i32*
65 // CHECK: br i1 [[C]]
66 int r;
67 if (__builtin_sub_overflow(x, y, &r))
68 overflowed();
69 return r;
70}
71
72unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
73 // CHECK-LABEL: define i32 @test_mul_overflow_uint_uint_uint
74 // CHECK-NOT: ext
75 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
76 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
77 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
78 // CHECK: store i32 [[Q]], i32*
79 // CHECK: br i1 [[C]]
80 unsigned r;
81 if (__builtin_mul_overflow(x, y, &r))
82 overflowed();
83 return r;
84}
85
86int test_mul_overflow_int_int_int(int x, int y) {
87 // CHECK-LABEL: define i32 @test_mul_overflow_int_int_int
88 // CHECK-NOT: ext
89 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
90 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
91 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
92 // CHECK: store i32 [[Q]], i32*
93 // CHECK: br i1 [[C]]
94 int r;
95 if (__builtin_mul_overflow(x, y, &r))
96 overflowed();
97 return r;
98}
99
100int test_add_overflow_uint_int_int(unsigned x, int y) {
101 // CHECK-LABEL: define i32 @test_add_overflow_uint_int_int
102 // CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
103 // CHECK: [[YE:%.+]] = sext i32 %{{.+}} to i33
104 // CHECK: [[S:%.+]] = call { i33, i1 } @llvm.sadd.with.overflow.i33(i33 [[XE]], i33 [[YE]])
105 // CHECK-DAG: [[Q:%.+]] = extractvalue { i33, i1 } [[S]], 0
106 // CHECK-DAG: [[C1:%.+]] = extractvalue { i33, i1 } [[S]], 1
107 // CHECK: [[QT:%.+]] = trunc i33 [[Q]] to i32
108 // CHECK: [[QTE:%.+]] = sext i32 [[QT]] to i33
109 // CHECK: [[C2:%.+]] = icmp ne i33 [[Q]], [[QTE]]
110 // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
111 // CHECK: store i32 [[QT]], i32*
112 // CHECK: br i1 [[C3]]
113 int r;
114 if (__builtin_add_overflow(x, y, &r))
115 overflowed();
116 return r;
117}
118
119_Bool test_add_overflow_uint_uint_bool(unsigned x, unsigned y) {
120 // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_uint_uint_bool
121 // CHECK-NOT: ext
122 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
123 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
124 // CHECK-DAG: [[C1:%.+]] = extractvalue { i32, i1 } [[S]], 1
125 // CHECK: [[QT:%.+]] = trunc i32 [[Q]] to i1
126 // CHECK: [[QTE:%.+]] = zext i1 [[QT]] to i32
127 // CHECK: [[C2:%.+]] = icmp ne i32 [[Q]], [[QTE]]
128 // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
129 // CHECK: [[QT2:%.+]] = zext i1 [[QT]] to i8
130 // CHECK: store i8 [[QT2]], i8*
131 // CHECK: br i1 [[C3]]
132 _Bool r;
133 if (__builtin_add_overflow(x, y, &r))
134 overflowed();
135 return r;
136}
137
138unsigned test_add_overflow_bool_bool_uint(_Bool x, _Bool y) {
139 // CHECK-LABEL: define i32 @test_add_overflow_bool_bool_uint
140 // CHECK: [[XE:%.+]] = zext i1 %{{.+}} to i32
141 // CHECK: [[YE:%.+]] = zext i1 %{{.+}} to i32
142 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[XE]], i32 [[YE]])
143 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
144 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
145 // CHECK: store i32 [[Q]], i32*
146 // CHECK: br i1 [[C]]
147 unsigned r;
148 if (__builtin_add_overflow(x, y, &r))
149 overflowed();
150 return r;
151}
152
153_Bool test_add_overflow_bool_bool_bool(_Bool x, _Bool y) {
154 // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_bool_bool_bool
155 // CHECK: [[S:%.+]] = call { i1, i1 } @llvm.uadd.with.overflow.i1(i1 %{{.+}}, i1 %{{.+}})
156 // CHECK-DAG: [[Q:%.+]] = extractvalue { i1, i1 } [[S]], 0
157 // CHECK-DAG: [[C:%.+]] = extractvalue { i1, i1 } [[S]], 1
158 // CHECK: [[QT2:%.+]] = zext i1 [[Q]] to i8
159 // CHECK: store i8 [[QT2]], i8*
160 // CHECK: br i1 [[C]]
161 _Bool r;
162 if (__builtin_add_overflow(x, y, &r))
163 overflowed();
164 return r;
165}
166
167int test_add_overflow_volatile(int x, int y) {
168 // CHECK-LABEL: define i32 @test_add_overflow_volatile
169 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
170 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
171 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
172 // CHECK: store volatile i32 [[Q]], i32*
173 // CHECK: br i1 [[C]]
174 volatile int result;
175 if (__builtin_add_overflow(x, y, &result))
176 overflowed();
177 return result;
178}
Michael Gottesman930ecdb2013-06-20 23:28:10 +0000179
180unsigned test_uadd_overflow(unsigned x, unsigned y) {
181// CHECK: @test_uadd_overflow
182// CHECK: %{{.+}} = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
183 unsigned result;
184 if (__builtin_uadd_overflow(x, y, &result))
185 return UnsignedErrorCode;
186 return result;
187}
188
189unsigned long test_uaddl_overflow(unsigned long x, unsigned long y) {
190// CHECK: @test_uaddl_overflow([[UL:i32|i64]] %x
191// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
192 unsigned long result;
193 if (__builtin_uaddl_overflow(x, y, &result))
194 return UnsignedLongErrorCode;
195 return result;
196}
197
198unsigned long long test_uaddll_overflow(unsigned long long x, unsigned long long y) {
199// CHECK: @test_uaddll_overflow
200// CHECK: %{{.+}} = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
201 unsigned long long result;
202 if (__builtin_uaddll_overflow(x, y, &result))
203 return UnsignedLongLongErrorCode;
204 return result;
205}
206
207unsigned test_usub_overflow(unsigned x, unsigned y) {
208// CHECK: @test_usub_overflow
209// CHECK: %{{.+}} = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
210 unsigned result;
211 if (__builtin_usub_overflow(x, y, &result))
212 return UnsignedErrorCode;
213 return result;
214}
215
216unsigned long test_usubl_overflow(unsigned long x, unsigned long y) {
217// CHECK: @test_usubl_overflow([[UL:i32|i64]] %x
218// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
219 unsigned long result;
220 if (__builtin_usubl_overflow(x, y, &result))
221 return UnsignedLongErrorCode;
222 return result;
223}
224
225unsigned long long test_usubll_overflow(unsigned long long x, unsigned long long y) {
226// CHECK: @test_usubll_overflow
227// CHECK: %{{.+}} = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
228 unsigned long long result;
229 if (__builtin_usubll_overflow(x, y, &result))
230 return UnsignedLongLongErrorCode;
231 return result;
232}
233
234unsigned test_umul_overflow(unsigned x, unsigned y) {
235// CHECK: @test_umul_overflow
236// CHECK: %{{.+}} = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
237 unsigned result;
238 if (__builtin_umul_overflow(x, y, &result))
239 return UnsignedErrorCode;
240 return result;
241}
242
243unsigned long test_umull_overflow(unsigned long x, unsigned long y) {
244// CHECK: @test_umull_overflow([[UL:i32|i64]] %x
245// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.umul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
246 unsigned long result;
247 if (__builtin_umull_overflow(x, y, &result))
248 return UnsignedLongErrorCode;
249 return result;
250}
251
252unsigned long long test_umulll_overflow(unsigned long long x, unsigned long long y) {
253// CHECK: @test_umulll_overflow
254// CHECK: %{{.+}} = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
255 unsigned long long result;
256 if (__builtin_umulll_overflow(x, y, &result))
257 return UnsignedLongLongErrorCode;
258 return result;
259}
260
261int test_sadd_overflow(int x, int y) {
262// CHECK: @test_sadd_overflow
263// CHECK: %{{.+}} = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
264 int result;
265 if (__builtin_sadd_overflow(x, y, &result))
266 return IntErrorCode;
267 return result;
268}
269
270long test_saddl_overflow(long x, long y) {
271// CHECK: @test_saddl_overflow([[UL:i32|i64]] %x
272// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.sadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
273 long result;
274 if (__builtin_saddl_overflow(x, y, &result))
275 return LongErrorCode;
276 return result;
277}
278
279long long test_saddll_overflow(long long x, long long y) {
280// CHECK: @test_saddll_overflow
281// CHECK: %{{.+}} = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
282 long long result;
283 if (__builtin_saddll_overflow(x, y, &result))
284 return LongLongErrorCode;
285 return result;
286}
287
288int test_ssub_overflow(int x, int y) {
289// CHECK: @test_ssub_overflow
290// CHECK: %{{.+}} = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
291 int result;
292 if (__builtin_ssub_overflow(x, y, &result))
293 return IntErrorCode;
294 return result;
295}
296
297long test_ssubl_overflow(long x, long y) {
298// CHECK: @test_ssubl_overflow([[UL:i32|i64]] %x
299// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.ssub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
300 long result;
301 if (__builtin_ssubl_overflow(x, y, &result))
302 return LongErrorCode;
303 return result;
304}
305
306long long test_ssubll_overflow(long long x, long long y) {
307// CHECK: @test_ssubll_overflow
308// CHECK: %{{.+}} = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
309 long long result;
310 if (__builtin_ssubll_overflow(x, y, &result))
311 return LongLongErrorCode;
312 return result;
313}
314
315int test_smul_overflow(int x, int y) {
316// CHECK: @test_smul_overflow
317// CHECK: %{{.+}} = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
318 int result;
319 if (__builtin_smul_overflow(x, y, &result))
320 return IntErrorCode;
321 return result;
322}
323
324long test_smull_overflow(long x, long y) {
325// CHECK: @test_smull_overflow([[UL:i32|i64]] %x
326// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.smul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
327 long result;
328 if (__builtin_smull_overflow(x, y, &result))
329 return LongErrorCode;
330 return result;
331}
332
333long long test_smulll_overflow(long long x, long long y) {
334// CHECK: @test_smulll_overflow
335// CHECK: %{{.+}} = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
336 long long result;
337 if (__builtin_smulll_overflow(x, y, &result))
338 return LongLongErrorCode;
339 return result;
340}