1 | // RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | opt -instnamer -S | FileCheck %s |
2 | // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN |
3 | // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL |
4 | // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-X32 |
5 | // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-X86 |
6 | |
7 | struct S { |
8 | double d; |
9 | int a, b; |
10 | virtual int f(); |
11 | }; |
12 | |
13 | // Check that type descriptor global is not modified by ASan. |
14 | // CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" } |
15 | |
16 | // Check that type mismatch handler is not modified by ASan. |
17 | // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} } |
18 | |
19 | // CHECK: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) |
20 | // CHECK-X86: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) |
21 | // CHECK-X32: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) |
22 | |
23 | struct T : S {}; |
24 | |
25 | // CHECK-LABEL: @_Z17reference_binding |
26 | void reference_binding(int *p, S *q) { |
27 | // C++ core issue 453: If an lvalue to which a reference is directly bound |
28 | // designates neither an existing object or function of an appropriate type, |
29 | // nor a region of storage of suitable size and alignment to contain an object |
30 | // of the reference's type, the behavior is undefined. |
31 | |
32 | // CHECK: icmp ne {{.*}}, null |
33 | |
34 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 |
35 | // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4 |
36 | |
37 | // CHECK: %[[PTRINT:.*]] = ptrtoint |
38 | // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 |
39 | // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 |
40 | int &r = *p; |
41 | |
42 | // A reference is not required to refer to an object within its lifetime. |
43 | // CHECK-NOT: __ubsan_handle_dynamic_type_cache_miss |
44 | S &r2 = *q; |
45 | } |
46 | |
47 | // CHECK-LABEL: @_Z13member_access |
48 | // CHECK-ASAN-LABEL: @_Z13member_access |
49 | void member_access(S *p) { |
50 | // (1a) Check 'p' is appropriately sized and aligned for member access. |
51 | |
52 | // CHECK: icmp ne {{.*}}, null |
53 | |
54 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 |
55 | // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24 |
56 | |
57 | // CHECK: %[[PTRINT:.*]] = ptrtoint |
58 | // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7 |
59 | // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 |
60 | |
61 | // (1b) Check that 'p' actually points to an 'S'. |
62 | |
63 | // CHECK: %[[VPTRADDR:.*]] = bitcast {{.*}} to i64* |
64 | // CHECK-NEXT: %[[VPTR:.*]] = load i64, i64* %[[VPTRADDR]] |
65 | // |
66 | // hash_16_bytes: |
67 | // |
68 | // If this number changes, it indicates that either the mangled name of ::S |
69 | // has changed, or that LLVM's hashing function has changed. The latter case |
70 | // is OK if the hashing function is still stable. |
71 | // |
72 | // The two hash values are for 64- and 32-bit Clang binaries, respectively. |
73 | // FIXME: We should produce a 64-bit value either way. |
74 | // |
75 | // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}}, %[[VPTR]] |
76 | // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023 |
77 | // CHECK-NEXT: lshr i64 {{.*}}, 47 |
78 | // CHECK-NEXT: xor i64 |
79 | // CHECK-NEXT: xor i64 %[[VPTR]] |
80 | // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023 |
81 | // CHECK-NEXT: lshr i64 {{.*}}, 47 |
82 | // CHECK-NEXT: xor i64 |
83 | // CHECK-NEXT: %[[HASH:.*]] = mul i64 {{.*}}, -7070675565921424023 |
84 | // |
85 | // Check the hash against the table: |
86 | // |
87 | // CHECK-NEXT: %[[IDX:.*]] = and i64 %{{.*}}, 127 |
88 | // CHECK-NEXT: getelementptr inbounds [128 x i64], [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %[[IDX]] |
89 | // CHECK-NEXT: %[[CACHEVAL:.*]] = load i64, i64* |
90 | // CHECK-NEXT: icmp eq i64 %[[CACHEVAL]], %[[HASH]] |
91 | // CHECK-NEXT: br i1 |
92 | |
93 | // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]]) |
94 | // CHECK-NOT: unreachable |
95 | // CHECK: {{.*}}: |
96 | |
97 | // (2) Check 'p->b' is appropriately sized and aligned for a load. |
98 | |
99 | // FIXME: Suppress this in the trivial case of a member access, because we |
100 | // know we've just checked the member access expression itself. |
101 | |
102 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 |
103 | // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4 |
104 | |
105 | // CHECK: %[[PTRINT:.*]] = ptrtoint |
106 | // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 |
107 | // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 |
108 | int k = p->b; |
109 | |
110 | // (3a) Check 'p' is appropriately sized and aligned for member function call. |
111 | |
112 | // CHECK: icmp ne {{.*}}, null |
113 | |
114 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 |
115 | // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24 |
116 | |
117 | // CHECK: %[[PTRINT:.*]] = ptrtoint |
118 | // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7 |
119 | // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 |
120 | |
121 | // (3b) Check that 'p' actually points to an 'S' |
122 | |
123 | // CHECK: load i64, i64* |
124 | // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}}, |
125 | // [...] |
126 | // CHECK: getelementptr inbounds [128 x i64], [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 % |
127 | // CHECK: br i1 |
128 | // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}}) |
129 | // CHECK-NOT: unreachable |
130 | // CHECK: {{.*}}: |
131 | |
132 | k = p->f(); |
133 | } |
134 | |
135 | // CHECK-LABEL: @_Z12lsh_overflow |
136 | int lsh_overflow(int a, int b) { |
137 | // CHECK: %[[RHS_INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 |
138 | // CHECK-NEXT: br i1 %[[RHS_INBOUNDS]], label %[[CHECK_BB:.*]], label %[[CONT_BB:.*]], |
139 | |
140 | // CHECK: [[CHECK_BB]]: |
141 | // CHECK-NEXT: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]] |
142 | // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]] |
143 | |
144 | // This is present for C++11 but not for C: C++ core issue 1457 allows a '1' |
145 | // to be shifted into the sign bit, but not out of it. |
146 | // CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1 |
147 | |
148 | // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0 |
149 | // CHECK-NEXT: br label %[[CONT_BB]] |
150 | |
151 | // CHECK: [[CONT_BB]]: |
152 | // CHECK-NEXT: %[[VALID_BASE:.*]] = phi i1 [ true, {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECK_BB]] ] |
153 | // CHECK-NEXT: %[[VALID:.*]] = and i1 %[[RHS_INBOUNDS]], %[[VALID_BASE]] |
154 | // CHECK-NEXT: br i1 %[[VALID]] |
155 | |
156 | // CHECK: call void @__ubsan_handle_shift_out_of_bounds |
157 | // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds |
158 | |
159 | // CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]] |
160 | // CHECK-NEXT: ret i32 %[[RET]] |
161 | return a << b; |
162 | } |
163 | |
164 | // CHECK-LABEL: @_Z9no_return |
165 | int no_return() { |
166 | // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) [[NR_NUW:#[0-9]+]] |
167 | // CHECK-NEXT: unreachable |
168 | } |
169 | |
170 | // CHECK-LABEL: @_Z9sour_bool |
171 | bool sour_bool(bool *p) { |
172 | // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 |
173 | // CHECK: br i1 %[[OK]] |
174 | // CHECK: call void @__ubsan_handle_load_invalid_value(i8* bitcast ({{.*}}), i64 {{.*}}) |
175 | return *p; |
176 | } |
177 | |
178 | enum E1 { e1a = 0, e1b = 127 } e1; |
179 | enum E2 { e2a = -1, e2b = 64 } e2; |
180 | enum E3 { e3a = (1u << 31) - 1 } e3; |
181 | |
182 | // CHECK-LABEL: @_Z14bad_enum_value |
183 | int bad_enum_value() { |
184 | // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127 |
185 | // CHECK: br i1 %[[E1]] |
186 | // CHECK: call void @__ubsan_handle_load_invalid_value( |
187 | int a = e1; |
188 | |
189 | // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127 |
190 | // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128 |
191 | // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]] |
192 | // CHECK: br i1 %[[E2]] |
193 | // CHECK: call void @__ubsan_handle_load_invalid_value( |
194 | int b = e2; |
195 | |
196 | // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647 |
197 | // CHECK: br i1 %[[E3]] |
198 | // CHECK: call void @__ubsan_handle_load_invalid_value( |
199 | int c = e3; |
200 | return a + b + c; |
201 | } |
202 | |
203 | // CHECK-LABEL: @_Z20bad_downcast_pointer |
204 | // DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer |
205 | void bad_downcast_pointer(S *p) { |
206 | // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null |
207 | // CHECK: br i1 %[[NONNULL]], |
208 | |
209 | // A null pointer access is guarded without -fsanitize=null. |
210 | // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null |
211 | // DOWNCAST-NULL: br i1 %[[NONNULL]], |
212 | |
213 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8( |
214 | // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24 |
215 | // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 |
216 | // CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0 |
217 | // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] |
218 | // CHECK: br i1 %[[E12]], |
219 | |
220 | // CHECK: call void @__ubsan_handle_type_mismatch |
221 | // CHECK: br label |
222 | |
223 | // CHECK: br i1 %{{.*}}, |
224 | |
225 | // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss |
226 | // CHECK: br label |
227 | (void) static_cast<T*>(p); |
228 | } |
229 | |
230 | // CHECK-LABEL: @_Z22bad_downcast_reference |
231 | void bad_downcast_reference(S &p) { |
232 | // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null |
233 | // CHECK-NOT: br i1 |
234 | |
235 | // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8( |
236 | // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24 |
237 | |
238 | // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 |
239 | // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0 |
240 | |
241 | // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] |
242 | // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]] |
243 | // CHECK: br i1 %[[E123]], |
244 | |
245 | // CHECK: call void @__ubsan_handle_type_mismatch |
246 | // CHECK: br label |
247 | |
248 | // CHECK: br i1 %{{.*}}, |
249 | |
250 | // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss |
251 | // CHECK: br label |
252 | (void) static_cast<T&>(p); |
253 | } |
254 | |
255 | // CHECK-LABEL: @_Z11array_index |
256 | int array_index(const int (&a)[4], int n) { |
257 | // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4 |
258 | // CHECK: br i1 %[[K1_OK]] |
259 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
260 | int k1 = a[n]; |
261 | |
262 | // CHECK: %[[R1_OK:.*]] = icmp ule i64 %{{.*}}, 4 |
263 | // CHECK: br i1 %[[R1_OK]] |
264 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
265 | const int *r1 = &a[n]; |
266 | |
267 | // CHECK: %[[K2_OK:.*]] = icmp ult i64 %{{.*}}, 8 |
268 | // CHECK: br i1 %[[K2_OK]] |
269 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
270 | int k2 = ((const int(&)[8])a)[n]; |
271 | |
272 | // CHECK: %[[K3_OK:.*]] = icmp ult i64 %{{.*}}, 4 |
273 | // CHECK: br i1 %[[K3_OK]] |
274 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
275 | int k3 = n[a]; |
276 | |
277 | return k1 + *r1 + k2; |
278 | } |
279 | |
280 | // CHECK-LABEL: @_Z17multi_array_index |
281 | int multi_array_index(int n, int m) { |
282 | int arr[4][6]; |
283 | |
284 | // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4 |
285 | // CHECK: br i1 %[[IDX1_OK]] |
286 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
287 | |
288 | // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6 |
289 | // CHECK: br i1 %[[IDX2_OK]] |
290 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
291 | return arr[n][m]; |
292 | } |
293 | |
294 | // CHECK-LABEL: @_Z11array_arith |
295 | int array_arith(const int (&a)[4], int n) { |
296 | // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4 |
297 | // CHECK: br i1 %[[K1_OK]] |
298 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
299 | const int *k1 = a + n; |
300 | |
301 | // CHECK: %[[K2_OK:.*]] = icmp ule i64 %{{.*}}, 8 |
302 | // CHECK: br i1 %[[K2_OK]] |
303 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
304 | const int *k2 = (const int(&)[8])a + n; |
305 | |
306 | return *k1 + *k2; |
307 | } |
308 | |
309 | struct ArrayMembers { |
310 | int a1[5]; |
311 | int a2[1]; |
312 | }; |
313 | // CHECK-LABEL: @_Z18struct_array_index |
314 | int struct_array_index(ArrayMembers *p, int n) { |
315 | // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5 |
316 | // CHECK: br i1 %[[IDX_OK]] |
317 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
318 | return p->a1[n]; |
319 | } |
320 | |
321 | // CHECK-LABEL: @_Z16flex_array_index |
322 | int flex_array_index(ArrayMembers *p, int n) { |
323 | // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( |
324 | return p->a2[n]; |
325 | } |
326 | |
327 | extern int incomplete[]; |
328 | // CHECK-LABEL: @_Z22incomplete_array_index |
329 | int incomplete_array_index(int n) { |
330 | // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( |
331 | return incomplete[n]; |
332 | } |
333 | |
334 | typedef __attribute__((ext_vector_type(4))) int V4I; |
335 | // CHECK-LABEL: @_Z12vector_index |
336 | int vector_index(V4I v, int n) { |
337 | // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4 |
338 | // CHECK: br i1 %[[IDX_OK]] |
339 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
340 | return v[n]; |
341 | } |
342 | |
343 | // CHECK-LABEL: @_Z12string_index |
344 | char string_index(int n) { |
345 | // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6 |
346 | // CHECK: br i1 %[[IDX_OK]] |
347 | // CHECK: call void @__ubsan_handle_out_of_bounds( |
348 | return "Hello"[n]; |
349 | } |
350 | |
351 | class A // align=4 |
352 | { |
353 | int a1, a2, a3; |
354 | }; |
355 | |
356 | class B // align=8 |
357 | { |
358 | long b1, b2; |
359 | }; |
360 | |
361 | class C : public A, public B // align=16 |
362 | { |
363 | alignas(16) int c1; |
364 | }; |
365 | |
366 | // Make sure we check the alignment of the pointer after subtracting any |
367 | // offset. The pointer before subtraction doesn't need to be aligned for |
368 | // the destination type. |
369 | |
370 | // CHECK-LABEL: define void @_Z16downcast_pointerP1B(%class.B* %b) |
371 | void downcast_pointer(B *b) { |
372 | (void) static_cast<C*>(b); |
373 | // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...) |
374 | // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16 |
375 | // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* |
376 | // null check goes here |
377 | // CHECK: [[FROM_PHI:%.+]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}} |
378 | // Objectsize check goes here |
379 | // CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[FROM_PHI]] to i64 |
380 | // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 |
381 | // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 |
382 | // AND the alignment test with the objectsize test. |
383 | // CHECK-NEXT: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] |
384 | // CHECK-NEXT: br i1 [[AND]] |
385 | } |
386 | |
387 | // CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* dereferenceable({{[0-9]+}}) %b) |
388 | void downcast_reference(B &b) { |
389 | (void) static_cast<C&>(b); |
390 | // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...) |
391 | // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16 |
392 | // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* |
393 | // Objectsize check goes here |
394 | // CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[C]] to i64 |
395 | // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 |
396 | // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 |
397 | // AND the alignment test with the objectsize test. |
398 | // CHECK: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] |
399 | // CHECK-NEXT: br i1 [[AND]] |
400 | } |
401 | |
402 | // |
403 | // CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** {{.*}} to i64), i64 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i64)) to i32) }> |
404 | // CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i32)) }> |
405 | // CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i32)) }> |
406 | void indirect_function_call(void (*p)(int)) { |
407 | // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i32 }>* |
408 | |
409 | // Signature check |
410 | // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 0, i32 0 |
411 | // CHECK-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] |
412 | // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 846595819 |
413 | // CHECK-NEXT: br i1 [[SIGCMP]] |
414 | |
415 | // RTTI pointer check |
416 | // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 0, i32 1 |
417 | // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, i32* [[RTTIPTR]] |
418 | // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] to i64 |
419 | // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} to i64 |
420 | // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], [[FuncAddrInt]] |
421 | // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to i8** |
422 | // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], align 8 |
423 | // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) |
424 | // CHECK-NEXT: br i1 [[RTTICMP]] |
425 | |
426 | p(42); |
427 | } |
428 | |
429 | namespace FunctionSanitizerVirtualCalls { |
430 | struct A { |
431 | virtual void f() {} |
432 | virtual void g() {} |
433 | void h() {} |
434 | }; |
435 | |
436 | struct B : virtual A { |
437 | virtual void b() {} |
438 | virtual void f(); |
439 | void g() final {} |
440 | static void q() {} |
441 | }; |
442 | |
443 | void B::f() {} |
444 | |
445 | void force_irgen() { |
446 | A a; |
447 | a.g(); |
448 | a.h(); |
449 | |
450 | B b; |
451 | b.f(); |
452 | b.b(); |
453 | b.g(); |
454 | B::q(); |
455 | } |
456 | |
457 | // CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls1B1fEv |
458 | // CHECK-NOT: prologue |
459 | // |
460 | // CHECK-LABEL: define void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv |
461 | // CHECK-NOT: prologue |
462 | // |
463 | // CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv() |
464 | // CHECK: prologue |
465 | // |
466 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev |
467 | // CHECK-NOT: prologue |
468 | // |
469 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv |
470 | // CHECK-NOT: prologue |
471 | // |
472 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv |
473 | // CHECK-NOT: prologue |
474 | // |
475 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev |
476 | // CHECK-NOT: prologue |
477 | // |
478 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv |
479 | // CHECK-NOT: prologue |
480 | // |
481 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv |
482 | // CHECK-NOT: prologue |
483 | // |
484 | // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv |
485 | // CHECK: prologue |
486 | |
487 | } |
488 | |
489 | namespace UpcastPointerTest { |
490 | struct S {}; |
491 | struct T : S { double d; }; |
492 | struct V : virtual S {}; |
493 | |
494 | // CHECK-LABEL: upcast_pointer |
495 | S* upcast_pointer(T* t) { |
496 | // Check for null pointer |
497 | // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null |
498 | // CHECK: br i1 %[[NONNULL]] |
499 | |
500 | // Check alignment |
501 | // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 |
502 | // CHECK: icmp eq i64 %[[MISALIGN]], 0 |
503 | |
504 | // CHECK: call void @__ubsan_handle_type_mismatch |
505 | return t; |
506 | } |
507 | |
508 | V getV(); |
509 | |
510 | // CHECK-LABEL: upcast_to_vbase |
511 | void upcast_to_vbase() { |
512 | // No need to check for null here, as we have a temporary here. |
513 | |
514 | // CHECK-NOT: br i1 |
515 | |
516 | // CHECK: call i64 @llvm.objectsize |
517 | // CHECK: call void @__ubsan_handle_type_mismatch |
518 | // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss |
519 | const S& s = getV(); |
520 | } |
521 | } |
522 | |
523 | struct nothrow {}; |
524 | void *operator new[](__SIZE_TYPE__, nothrow) noexcept; |
525 | |
526 | namespace NothrowNew { |
527 | struct X { X(); }; |
528 | |
529 | // CHECK-LABEL: define{{.*}}nothrow_new_trivial |
530 | void *nothrow_new_trivial() { |
531 | // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null |
532 | // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] |
533 | |
534 | // CHECK: [[nonnull]]: |
535 | // CHECK: llvm.objectsize |
536 | // CHECK: icmp uge i64 {{.*}}, 123456, |
537 | // CHECK: br i1 |
538 | // |
539 | // CHECK: call {{.*}}__ubsan_handle_type_mismatch |
540 | // |
541 | // CHECK: [[null]]: |
542 | // CHECK-NOT: {{ }}br{{ }} |
543 | // CHECK: ret |
544 | return new (nothrow{}) char[123456]; |
545 | } |
546 | |
547 | // CHECK-LABEL: define{{.*}}nothrow_new_nontrivial |
548 | void *nothrow_new_nontrivial() { |
549 | // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null |
550 | // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] |
551 | |
552 | // CHECK: [[nonnull]]: |
553 | // CHECK: llvm.objectsize |
554 | // CHECK: icmp uge i64 {{.*}}, 123456, |
555 | // CHECK: br i1 |
556 | // |
557 | // CHECK: call {{.*}}__ubsan_handle_type_mismatch |
558 | // |
559 | // CHECK: call {{.*}}_ZN10NothrowNew1XC1Ev |
560 | // |
561 | // CHECK: [[null]]: |
562 | // CHECK-NOT: {{ }}br{{ }} |
563 | // CHECK: ret |
564 | return new (nothrow{}) X[123456]; |
565 | } |
566 | |
567 | // CHECK-LABEL: define{{.*}}throwing_new |
568 | void *throwing_new(int size) { |
569 | // CHECK: icmp ne i8*{{.*}}, null |
570 | // CHECK: %[[size:.*]] = mul |
571 | // CHECK: llvm.objectsize |
572 | // CHECK: icmp uge i64 {{.*}}, %[[size]], |
573 | // CHECK: %[[ok:.*]] = and |
574 | // CHECK: br i1 %[[ok]], label %[[good:.*]], label %[[bad:[^,]*]] |
575 | // |
576 | // CHECK: [[bad]]: |
577 | // CHECK: call {{.*}}__ubsan_handle_type_mismatch |
578 | // |
579 | // CHECK: [[good]]: |
580 | // CHECK-NOT: {{ }}br{{ }} |
581 | // CHECK: ret |
582 | return new char[size]; |
583 | } |
584 | |
585 | // CHECK-LABEL: define{{.*}}nothrow_new_zero_size |
586 | void *nothrow_new_zero_size() { |
587 | // CHECK: %[[nonnull:.*]] = icmp ne i8*{{.*}}, null |
588 | // CHECK-NOT: llvm.objectsize |
589 | // CHECK: br i1 %[[nonnull]], label %[[good:.*]], label %[[bad:[^,]*]] |
590 | // |
591 | // CHECK: [[bad]]: |
592 | // CHECK: call {{.*}}__ubsan_handle_type_mismatch |
593 | // |
594 | // CHECK: [[good]]: |
595 | // CHECK-NOT: {{ }}br{{ }} |
596 | // CHECK: ret |
597 | return new char[0]; |
598 | } |
599 | |
600 | // CHECK-LABEL: define{{.*}}throwing_new_zero_size |
601 | void *throwing_new_zero_size() { |
602 | // Nothing to check here. |
603 | // CHECK-NOT: __ubsan_handle_type_mismatch |
604 | return new (nothrow{}) char[0]; |
605 | // CHECK: ret |
606 | } |
607 | } |
608 | |
609 | struct ThisAlign { |
610 | void this_align_lambda(); |
611 | void this_align_lambda_2(); |
612 | }; |
613 | void ThisAlign::this_align_lambda() { |
614 | // CHECK-LABEL: define internal %struct.ThisAlign* @"_ZZN9ThisAlign17this_align_lambdaEvENK3$_0clEv" |
615 | // CHECK-SAME: (%{{.*}}* %[[this:[^)]*]]) |
616 | // CHECK: %[[this_addr:.*]] = alloca |
617 | // CHECK: store %{{.*}}* %[[this]], %{{.*}}** %[[this_addr]], |
618 | // CHECK: %[[this_inner:.*]] = load %{{.*}}*, %{{.*}}** %[[this_addr]], |
619 | // CHECK: %[[this_outer_addr:.*]] = getelementptr inbounds %{{.*}}, %{{.*}}* %[[this_inner]], i32 0, i32 0 |
620 | // CHECK: %[[this_outer:.*]] = load %{{.*}}*, %{{.*}}** %[[this_outer_addr]], |
621 | // |
622 | // CHECK: %[[this_inner_isnonnull:.*]] = icmp ne %{{.*}}* %[[this_inner]], null |
623 | // CHECK: %[[this_inner_asint:.*]] = ptrtoint %{{.*}}* %[[this_inner]] to i |
624 | // CHECK: %[[this_inner_misalignment:.*]] = and i{{32|64}} %[[this_inner_asint]], {{3|7}}, |
625 | // CHECK: %[[this_inner_isaligned:.*]] = icmp eq i{{32|64}} %[[this_inner_misalignment]], 0 |
626 | // CHECK: %[[this_inner_valid:.*]] = and i1 %[[this_inner_isnonnull]], %[[this_inner_isaligned]], |
627 | // CHECK: br i1 %[[this_inner_valid:.*]] |
628 | [&] { return this; } (); |
629 | } |
630 | |
631 | namespace CopyValueRepresentation { |
632 | // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_ |
633 | // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value |
634 | // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S4aSEOS0_ |
635 | // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value |
636 | // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S1C2ERKS0_ |
637 | // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value |
638 | // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S2C2ERKS0_ |
639 | // CHECK: __ubsan_handle_load_invalid_value |
640 | // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S5C2ERKS0_ |
641 | // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value |
642 | |
643 | struct CustomCopy { CustomCopy(); CustomCopy(const CustomCopy&); }; |
644 | struct S1 { |
645 | CustomCopy CC; |
646 | bool b; |
647 | }; |
648 | void callee1(S1); |
649 | void test1() { |
650 | S1 s11; |
651 | callee1(s11); |
652 | S1 s12; |
653 | s12 = s11; |
654 | } |
655 | |
656 | static bool some_global_bool; |
657 | struct ExprCopy { |
658 | ExprCopy(); |
659 | ExprCopy(const ExprCopy&, bool b = some_global_bool); |
660 | }; |
661 | struct S2 { |
662 | ExprCopy EC; |
663 | bool b; |
664 | }; |
665 | void callee2(S2); |
666 | void test2(void) { |
667 | S2 s21; |
668 | callee2(s21); |
669 | S2 s22; |
670 | s22 = s21; |
671 | } |
672 | |
673 | struct CustomAssign { CustomAssign &operator=(const CustomAssign&); }; |
674 | struct S3 { |
675 | CustomAssign CA; |
676 | bool b; |
677 | }; |
678 | void test3() { |
679 | S3 x, y; |
680 | x = y; |
681 | } |
682 | |
683 | struct CustomMove { |
684 | CustomMove(); |
685 | CustomMove(const CustomMove&&); |
686 | CustomMove &operator=(const CustomMove&&); |
687 | }; |
688 | struct S4 { |
689 | CustomMove CM; |
690 | bool b; |
691 | }; |
692 | void test4() { |
693 | S4 x, y; |
694 | x = static_cast<S4&&>(y); |
695 | } |
696 | |
697 | struct EnumCustomCopy { |
698 | EnumCustomCopy(); |
699 | EnumCustomCopy(const EnumCustomCopy&); |
700 | }; |
701 | struct S5 { |
702 | EnumCustomCopy ECC; |
703 | bool b; |
704 | }; |
705 | void callee5(S5); |
706 | void test5() { |
707 | S5 s51; |
708 | callee5(s51); |
709 | S5 s52; |
710 | s52 = s51; |
711 | } |
712 | } |
713 | |
714 | void ThisAlign::this_align_lambda_2() { |
715 | // CHECK-LABEL: define internal void @"_ZZN9ThisAlign19this_align_lambda_2EvENK3$_1clEv" |
716 | // CHECK-SAME: (%{{.*}}* %[[this:[^)]*]]) |
717 | // CHECK: %[[this_addr:.*]] = alloca |
718 | // CHECK: store %{{.*}}* %[[this]], %{{.*}}** %[[this_addr]], |
719 | // CHECK: %[[this_inner:.*]] = load %{{.*}}*, %{{.*}}** %[[this_addr]], |
720 | // |
721 | // Do not perform a null check on the 'this' pointer if the function might be |
722 | // called from a static invoker. |
723 | // CHECK-NOT: icmp ne %{{.*}}* %[[this_inner]], null |
724 | auto *p = +[] {}; |
725 | p(); |
726 | } |
727 | |
728 | // CHECK: attributes [[NR_NUW]] = { noreturn nounwind } |
729 | |