blob: b09f7ddfaedffeb85f0084e5a6e37601fecaaddd [file] [log] [blame]
Roman Lebedevb69ba222018-07-30 18:58:30 +00001// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
2// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
3// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
4// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
5
6// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
7// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
8
9// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
10// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
11// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
12// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
13// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
14// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
15
16// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
17// CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" }
18// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 0 }
19
20// ========================================================================== //
21// The expected true-positives. These are implicit conversions, and they truncate.
22// ========================================================================== //
23
24// CHECK-LABEL: @unsigned_int_to_unsigned_char
25unsigned char unsigned_int_to_unsigned_char(unsigned int src) {
26 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
27 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
28 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
29 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
30 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
31 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
32 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
33 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
35 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
36 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
37 // CHECK-SANITIZE: [[CONT]]:
38 // CHECK: ret i8 %[[DST]]
39#line 100
40 return src;
41}
42
43// CHECK-LABEL: @signed_int_to_unsigned_char
44unsigned char signed_int_to_unsigned_char(signed int src) {
45 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
46 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
47 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
48 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
49 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
50 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
51 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
52 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
53 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
54 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
55 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
56 // CHECK-SANITIZE: [[CONT]]:
57 // CHECK: ret i8 %[[DST]]
58#line 200
59 return src;
60}
61
62// CHECK-LABEL: @unsigned_int_to_signed_char
63signed char unsigned_int_to_signed_char(unsigned int src) {
64 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
65 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
66 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
67 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
68 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
69 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
70 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
71 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
72 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
73 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
74 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
75 // CHECK-SANITIZE: [[CONT]]:
76 // CHECK: ret i8 %[[DST]]
77#line 300
78 return src;
79}
80
81// CHECK-LABEL: @signed_int_to_signed_char
82signed char signed_int_to_signed_char(signed int src) {
83 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
84 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
85 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
86 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
87 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
88 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
89 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
90 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
91 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
92 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
93 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
94 // CHECK-SANITIZE: [[CONT]]:
95 // CHECK: ret i8 %[[DST]]
96#line 400
97 return src;
98}
99
100// ========================================================================== //
101// Check canonical type stuff
102// ========================================================================== //
103
104typedef unsigned int uint32_t;
105typedef unsigned char uint8_t;
106
107// CHECK-LABEL: @uint32_to_uint8
108uint8_t uint32_to_uint8(uint32_t src) {
109 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
110 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
111 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
112 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
113 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
114 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
115 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
116 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
117 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
118 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
119 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
120 // CHECK-SANITIZE: [[CONT]]:
121 // CHECK: ret i8 %[[DST]]
122#line 500
123 return src;
124}
125
126// ========================================================================== //
127// Check that explicit conversion does not interfere with implicit conversion
128// ========================================================================== //
129// These contain one implicit truncating conversion, and one explicit truncating conversion.
130// We want to make sure that we still diagnose the implicit conversion.
131
132// Implicit truncation after explicit truncation.
133// CHECK-LABEL: @explicit_conversion_interference0
134unsigned char explicit_conversion_interference0(unsigned int c) {
135 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
136 // CHECK-SANITIZE: call
137 // CHECK-SANITIZE-NOT: call
138 // CHECK: }
139 return (unsigned short)c;
140}
141
142// Implicit truncation before explicit truncation.
143// CHECK-LABEL: @explicit_conversion_interference1
144unsigned char explicit_conversion_interference1(unsigned int c) {
145 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
146 // CHECK-SANITIZE: call
147 // CHECK-SANITIZE-NOT: call
148 // CHECK: }
149 unsigned short b;
150 return (unsigned char)(b = c);
151}
152
153// ========================================================================== //
154// The expected true-negatives.
155// ========================================================================== //
156
157// Sanitization is explicitly disabled.
158// ========================================================================== //
159
160// CHECK-LABEL: @blacklist_0
161__attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) {
162 // We are not in "undefined" group, so that doesn't work.
163 // CHECK-SANITIZE: call
164 // CHECK: }
165 return src;
166}
167
168// CHECK-LABEL: @blacklist_1
169__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_1(unsigned int src) {
170 // CHECK-SANITIZE-NOT: call
171 // CHECK: }
172 return src;
173}
174
175// CHECK-LABEL: @blacklist_2
176__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_2(unsigned int src) {
177 // CHECK-SANITIZE-NOT: call
178 // CHECK: }
179 return src;
180}
181
182// Explicit truncating conversions.
183// ========================================================================== //
184
185// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
186unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {
187 // CHECK-SANITIZE-NOT: call
188 // CHECK: }
189 return (unsigned char)src;
190}
191
192// CHECK-LABEL: @explicit_signed_int_to_unsigned_char
193unsigned char explicit_signed_int_to_unsigned_char(signed int src) {
194 // CHECK-SANITIZE-NOT: call
195 // CHECK: }
196 return (unsigned char)src;
197}
198
199// CHECK-LABEL: @explicit_unsigned_int_to_signed_char
200signed char explicit_unsigned_int_to_signed_char(unsigned int src) {
201 // CHECK-SANITIZE-NOT: call
202 // CHECK: }
203 return (signed char)src;
204}
205
206// CHECK-LABEL: @explicit_signed_int_to_signed_char
207signed char explicit_signed_int_to_signed_char(signed int src) {
208 // CHECK-SANITIZE-NOT: call
209 // CHECK: }
210 return (signed char)src;
211}
212
213// Explicit NOP conversions.
214// ========================================================================== //
215
216// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
217unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
218 // CHECK-SANITIZE-NOT: call
219 // CHECK: }
220 return (unsigned int)src;
221}
222
223// CHECK-LABEL: @explicit_signed_int_to_signed_int
224signed int explicit_signed_int_to_signed_int(signed int src) {
225 // CHECK-SANITIZE-NOT: call
226 // CHECK: }
227 return (signed int)src;
228}
229
230// CHECK-LABEL: @explicit_unsigned_char_to_signed_char
231unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {
232 // CHECK-SANITIZE-NOT: call
233 // CHECK: }
234 return (unsigned char)src;
235}
236
237// CHECK-LABEL: @explicit_signed_char_to_signed_char
238signed char explicit_signed_char_to_signed_char(signed char src) {
239 // CHECK-SANITIZE-NOT: call
240 // CHECK: }
241 return (signed char)src;
242}
243
244// upcasts.
245// ========================================================================== //
246
247// CHECK-LABEL: @unsigned_char_to_unsigned_int
248unsigned int unsigned_char_to_unsigned_int(unsigned char src) {
249 // CHECK-SANITIZE-NOT: call
250 // CHECK: }
251 return src;
252}
253
254// CHECK-LABEL: @signed_char_to_unsigned_int
255unsigned int signed_char_to_unsigned_int(signed char src) {
256 // CHECK-SANITIZE-NOT: call
257 // CHECK: }
258 return src;
259}
260
261// CHECK-LABEL: @unsigned_char_to_signed_int
262signed int unsigned_char_to_signed_int(unsigned char src) {
263 // CHECK-SANITIZE-NOT: call
264 // CHECK: }
265 return src;
266}
267
268// CHECK-LABEL: @signed_char_to_signed_int
269signed int signed_char_to_signed_int(signed char src) {
270 // CHECK-SANITIZE-NOT: call
271 // CHECK: }
272 return src;
273}
274
275// Explicit upcasts.
276// ========================================================================== //
277
278// CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int
279unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) {
280 // CHECK-SANITIZE-NOT: call
281 // CHECK: }
282 return (unsigned int)src;
283}
284
285// CHECK-LABEL: @explicit_signed_char_to_unsigned_int
286unsigned int explicit_signed_char_to_unsigned_int(signed char src) {
287 // CHECK-SANITIZE-NOT: call
288 // CHECK: }
289 return (unsigned int)src;
290}
291
292// CHECK-LABEL: @explicit_unsigned_char_to_signed_int
293signed int explicit_unsigned_char_to_signed_int(unsigned char src) {
294 // CHECK-SANITIZE-NOT: call
295 // CHECK: }
296 return (signed int)src;
297}
298
299// CHECK-LABEL: @explicit_signed_char_to_signed_int
300signed int explicit_signed_char_to_signed_int(signed char src) {
301 // CHECK-SANITIZE-NOT: call
302 // CHECK: }
303 return (signed int)src;
304}
305
306// conversions to to boolean type are not counted as truncation.
307// ========================================================================== //
308
309// CHECK-LABEL: @unsigned_int_to_bool
310_Bool unsigned_int_to_bool(unsigned int src) {
311 // CHECK-SANITIZE-NOT: call
312 // CHECK: }
313 return src;
314}
315
316// CHECK-LABEL: @signed_int_to_bool
317_Bool signed_int_to_bool(signed int src) {
318 // CHECK-SANITIZE-NOT: call
319 // CHECK: }
320 return src;
321}
322
323// CHECK-LABEL: @explicit_unsigned_int_to_bool
324_Bool explicit_unsigned_int_to_bool(unsigned int src) {
325 // CHECK-SANITIZE-NOT: call
326 // CHECK: }
327 return (_Bool)src;
328}
329
330// CHECK-LABEL: @explicit_signed_int_to_bool
331_Bool explicit_signed_int_to_bool(signed int src) {
332 // CHECK-SANITIZE-NOT: call
333 // CHECK: }
334 return (_Bool)src;
335}
336
337// Explicit truncating conversions from pointer to a much-smaller integer.
338// Can not have an implicit conversion from pointer to an integer.
339// Can not have an implicit conversion between two enums.
340// ========================================================================== //
341
342// CHECK-LABEL: @explicit_voidptr_to_unsigned_char
343unsigned char explicit_voidptr_to_unsigned_char(void *src) {
344 // CHECK-SANITIZE-NOT: call
345 // CHECK: }
346 return (unsigned char)src;
347}
348
349// CHECK-LABEL: @explicit_voidptr_to_signed_char
350signed char explicit_voidptr_to_signed_char(void *src) {
351 // CHECK-SANITIZE-NOT: call
352 // CHECK: }
353 return (signed char)src;
354}
355
356// Implicit truncating conversions from floating-point may result in precision loss.
357// ========================================================================== //
358
359// CHECK-LABEL: @float_to_unsigned_int
360unsigned int float_to_unsigned_int(float src) {
361 // CHECK-SANITIZE-NOT: call
362 // CHECK: }
363 return src;
364}
365
366// CHECK-LABEL: @float_to_signed_int
367signed int float_to_signed_int(float src) {
368 // CHECK-SANITIZE-NOT: call
369 // CHECK: }
370 return src;
371}
372
373// CHECK-LABEL: @double_to_unsigned_int
374unsigned int double_to_unsigned_int(double src) {
375 // CHECK-SANITIZE-NOT: call
376 // CHECK: }
377 return src;
378}
379
380// CHECK-LABEL: @double_to_signed_int
381signed int double_to_signed_int(double src) {
382 // CHECK-SANITIZE-NOT: call
383 // CHECK: }
384 return src;
385}
386
387// Implicit truncating conversions between fp may result in precision loss.
388// ========================================================================== //
389
390// CHECK-LABEL: @double_to_float
391float double_to_float(double src) {
392 // CHECK-SANITIZE-NOT: call
393 // CHECK: }
394 return src;
395}