1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s |
2 | // RUN: %clang_cc1 -DDYNAMIC -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s |
3 | |
4 | #ifndef DYNAMIC |
5 | #define OBJECT_SIZE_BUILTIN __builtin_object_size |
6 | #else |
7 | #define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size |
8 | #endif |
9 | |
10 | #define strcpy(dest, src) \ |
11 | ((OBJECT_SIZE_BUILTIN(dest, 0) != -1ULL) \ |
12 | ? __builtin___strcpy_chk (dest, src, OBJECT_SIZE_BUILTIN(dest, 1)) \ |
13 | : __inline_strcpy_chk(dest, src)) |
14 | |
15 | static char *__inline_strcpy_chk (char *dest, const char *src) { |
16 | return __builtin___strcpy_chk(dest, src, OBJECT_SIZE_BUILTIN(dest, 1)); |
17 | } |
18 | |
19 | char gbuf[63]; |
20 | char *gp; |
21 | int gi, gj; |
22 | |
23 | // CHECK-LABEL: define void @test1 |
24 | void test1() { |
25 | // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 4), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 59) |
26 | strcpy(&gbuf[4], "Hi there"); |
27 | } |
28 | |
29 | // CHECK-LABEL: define void @test2 |
30 | void test2() { |
31 | // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 63) |
32 | strcpy(gbuf, "Hi there"); |
33 | } |
34 | |
35 | // CHECK-LABEL: define void @test3 |
36 | void test3() { |
37 | // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 1, i64 37), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 0) |
38 | strcpy(&gbuf[100], "Hi there"); |
39 | } |
40 | |
41 | // CHECK-LABEL: define void @test4 |
42 | void test4() { |
43 | // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 -1), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 0) |
44 | strcpy((char*)(void*)&gbuf[-1], "Hi there"); |
45 | } |
46 | |
47 | // CHECK-LABEL: define void @test5 |
48 | void test5() { |
49 | // CHECK: = load i8*, i8** @gp |
50 | // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
51 | strcpy(gp, "Hi there"); |
52 | } |
53 | |
54 | // CHECK-LABEL: define void @test6 |
55 | void test6() { |
56 | char buf[57]; |
57 | |
58 | // CHECK: = call i8* @__strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 53) |
59 | strcpy(&buf[4], "Hi there"); |
60 | } |
61 | |
62 | // CHECK-LABEL: define void @test7 |
63 | void test7() { |
64 | int i; |
65 | // Ensure we only evaluate the side-effect once. |
66 | // CHECK: = add |
67 | // CHECK-NOT: = add |
68 | // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i64 63) |
69 | strcpy((++i, gbuf), "Hi there"); |
70 | } |
71 | |
72 | // CHECK-LABEL: define void @test8 |
73 | void test8() { |
74 | char *buf[50]; |
75 | // CHECK-NOT: __strcpy_chk |
76 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
77 | strcpy(buf[++gi], "Hi there"); |
78 | } |
79 | |
80 | // CHECK-LABEL: define void @test9 |
81 | void test9() { |
82 | // CHECK-NOT: __strcpy_chk |
83 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
84 | strcpy((char *)((++gi) + gj), "Hi there"); |
85 | } |
86 | |
87 | // CHECK-LABEL: define void @test10 |
88 | char **p; |
89 | void test10() { |
90 | // CHECK-NOT: __strcpy_chk |
91 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
92 | strcpy(*(++p), "Hi there"); |
93 | } |
94 | |
95 | // CHECK-LABEL: define void @test11 |
96 | void test11() { |
97 | // CHECK-NOT: __strcpy_chk |
98 | // CHECK: = call i8* @__inline_strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
99 | strcpy(gp = gbuf, "Hi there"); |
100 | } |
101 | |
102 | // CHECK-LABEL: define void @test12 |
103 | void test12() { |
104 | // CHECK-NOT: __strcpy_chk |
105 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
106 | strcpy(++gp, "Hi there"); |
107 | } |
108 | |
109 | // CHECK-LABEL: define void @test13 |
110 | void test13() { |
111 | // CHECK-NOT: __strcpy_chk |
112 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
113 | strcpy(gp++, "Hi there"); |
114 | } |
115 | |
116 | // CHECK-LABEL: define void @test14 |
117 | void test14() { |
118 | // CHECK-NOT: __strcpy_chk |
119 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
120 | strcpy(--gp, "Hi there"); |
121 | } |
122 | |
123 | // CHECK-LABEL: define void @test15 |
124 | void test15() { |
125 | // CHECK-NOT: __strcpy_chk |
126 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{..*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
127 | strcpy(gp--, "Hi there"); |
128 | } |
129 | |
130 | // CHECK-LABEL: define void @test16 |
131 | void test16() { |
132 | // CHECK-NOT: __strcpy_chk |
133 | // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0)) |
134 | strcpy(gp += 1, "Hi there"); |
135 | } |
136 | |
137 | // CHECK-LABEL: @test17 |
138 | void test17() { |
139 | // CHECK: store i32 -1 |
140 | gi = OBJECT_SIZE_BUILTIN(gp++, 0); |
141 | // CHECK: store i32 -1 |
142 | gi = OBJECT_SIZE_BUILTIN(gp++, 1); |
143 | // CHECK: store i32 0 |
144 | gi = OBJECT_SIZE_BUILTIN(gp++, 2); |
145 | // CHECK: store i32 0 |
146 | gi = OBJECT_SIZE_BUILTIN(gp++, 3); |
147 | } |
148 | |
149 | // CHECK-LABEL: @test18 |
150 | unsigned test18(int cond) { |
151 | int a[4], b[4]; |
152 | // CHECK: phi i32* |
153 | // CHECK: call i64 @llvm.objectsize.i64 |
154 | return OBJECT_SIZE_BUILTIN(cond ? a : b, 0); |
155 | } |
156 | |
157 | // CHECK-LABEL: @test19 |
158 | void test19() { |
159 | struct { |
160 | int a, b; |
161 | } foo; |
162 | |
163 | // CHECK: store i32 8 |
164 | gi = OBJECT_SIZE_BUILTIN(&foo.a, 0); |
165 | // CHECK: store i32 4 |
166 | gi = OBJECT_SIZE_BUILTIN(&foo.a, 1); |
167 | // CHECK: store i32 8 |
168 | gi = OBJECT_SIZE_BUILTIN(&foo.a, 2); |
169 | // CHECK: store i32 4 |
170 | gi = OBJECT_SIZE_BUILTIN(&foo.a, 3); |
171 | |
172 | // CHECK: store i32 4 |
173 | gi = OBJECT_SIZE_BUILTIN(&foo.b, 0); |
174 | // CHECK: store i32 4 |
175 | gi = OBJECT_SIZE_BUILTIN(&foo.b, 1); |
176 | // CHECK: store i32 4 |
177 | gi = OBJECT_SIZE_BUILTIN(&foo.b, 2); |
178 | // CHECK: store i32 4 |
179 | gi = OBJECT_SIZE_BUILTIN(&foo.b, 3); |
180 | } |
181 | |
182 | // CHECK-LABEL: @test20 |
183 | void test20() { |
184 | struct { int t[10]; } t[10]; |
185 | |
186 | // CHECK: store i32 380 |
187 | gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 0); |
188 | // CHECK: store i32 20 |
189 | gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 1); |
190 | // CHECK: store i32 380 |
191 | gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 2); |
192 | // CHECK: store i32 20 |
193 | gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 3); |
194 | } |
195 | |
196 | // CHECK-LABEL: @test21 |
197 | void test21() { |
198 | struct { int t; } t; |
199 | |
200 | // CHECK: store i32 0 |
201 | gi = OBJECT_SIZE_BUILTIN(&t + 1, 0); |
202 | // CHECK: store i32 0 |
203 | gi = OBJECT_SIZE_BUILTIN(&t + 1, 1); |
204 | // CHECK: store i32 0 |
205 | gi = OBJECT_SIZE_BUILTIN(&t + 1, 2); |
206 | // CHECK: store i32 0 |
207 | gi = OBJECT_SIZE_BUILTIN(&t + 1, 3); |
208 | |
209 | // CHECK: store i32 0 |
210 | gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 0); |
211 | // CHECK: store i32 0 |
212 | gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 1); |
213 | // CHECK: store i32 0 |
214 | gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 2); |
215 | // CHECK: store i32 0 |
216 | gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 3); |
217 | } |
218 | |
219 | // CHECK-LABEL: @test22 |
220 | void test22() { |
221 | struct { int t[10]; } t[10]; |
222 | |
223 | // CHECK: store i32 0 |
224 | gi = OBJECT_SIZE_BUILTIN(&t[10], 0); |
225 | // CHECK: store i32 0 |
226 | gi = OBJECT_SIZE_BUILTIN(&t[10], 1); |
227 | // CHECK: store i32 0 |
228 | gi = OBJECT_SIZE_BUILTIN(&t[10], 2); |
229 | // CHECK: store i32 0 |
230 | gi = OBJECT_SIZE_BUILTIN(&t[10], 3); |
231 | |
232 | // CHECK: store i32 0 |
233 | gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 0); |
234 | // CHECK: store i32 0 |
235 | gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 1); |
236 | // CHECK: store i32 0 |
237 | gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 2); |
238 | // CHECK: store i32 0 |
239 | gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 3); |
240 | |
241 | // CHECK: store i32 0 |
242 | gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 0); |
243 | // CHECK: store i32 0 |
244 | gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 1); |
245 | // CHECK: store i32 0 |
246 | gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 2); |
247 | // CHECK: store i32 0 |
248 | gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 3); |
249 | |
250 | // CHECK: store i32 0 |
251 | gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); |
252 | // CHECK: store i32 0 |
253 | gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); |
254 | // CHECK: store i32 0 |
255 | gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); |
256 | // CHECK: store i32 0 |
257 | gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); |
258 | } |
259 | |
260 | struct Test23Ty { int a; int t[10]; }; |
261 | |
262 | // CHECK-LABEL: @test23 |
263 | void test23(struct Test23Ty *p) { |
264 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
265 | gi = OBJECT_SIZE_BUILTIN(p, 0); |
266 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
267 | gi = OBJECT_SIZE_BUILTIN(p, 1); |
268 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
269 | gi = OBJECT_SIZE_BUILTIN(p, 2); |
270 | // Note: this is currently fixed at 0 because LLVM doesn't have sufficient |
271 | // data to correctly handle type=3 |
272 | // CHECK: store i32 0 |
273 | gi = OBJECT_SIZE_BUILTIN(p, 3); |
274 | |
275 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
276 | gi = OBJECT_SIZE_BUILTIN(&p->a, 0); |
277 | // CHECK: store i32 4 |
278 | gi = OBJECT_SIZE_BUILTIN(&p->a, 1); |
279 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
280 | gi = OBJECT_SIZE_BUILTIN(&p->a, 2); |
281 | // CHECK: store i32 4 |
282 | gi = OBJECT_SIZE_BUILTIN(&p->a, 3); |
283 | |
284 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
285 | gi = OBJECT_SIZE_BUILTIN(&p->t[5], 0); |
286 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
287 | gi = OBJECT_SIZE_BUILTIN(&p->t[5], 1); |
288 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
289 | gi = OBJECT_SIZE_BUILTIN(&p->t[5], 2); |
290 | // CHECK: store i32 20 |
291 | gi = OBJECT_SIZE_BUILTIN(&p->t[5], 3); |
292 | } |
293 | |
294 | // PR24493 -- ICE if OBJECT_SIZE_BUILTIN called with NULL and (Type & 1) != 0 |
295 | // CHECK-LABEL: @test24 |
296 | void test24() { |
297 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
298 | gi = OBJECT_SIZE_BUILTIN((void*)0, 0); |
299 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
300 | gi = OBJECT_SIZE_BUILTIN((void*)0, 1); |
301 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 |
302 | gi = OBJECT_SIZE_BUILTIN((void*)0, 2); |
303 | // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. |
304 | // Hopefully will be lowered properly in the future. |
305 | // CHECK: store i32 0 |
306 | gi = OBJECT_SIZE_BUILTIN((void*)0, 3); |
307 | } |
308 | |
309 | // CHECK-LABEL: @test25 |
310 | void test25() { |
311 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
312 | gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 0); |
313 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
314 | gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 1); |
315 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 |
316 | gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 2); |
317 | // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. |
318 | // Hopefully will be lowered properly in the future. |
319 | // CHECK: store i32 0 |
320 | gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 3); |
321 | |
322 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
323 | gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 0); |
324 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
325 | gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 1); |
326 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 |
327 | gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 2); |
328 | // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. |
329 | // Hopefully will be lowered properly in the future. |
330 | // CHECK: store i32 0 |
331 | gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 3); |
332 | } |
333 | |
334 | // CHECK-LABEL: @test26 |
335 | void test26() { |
336 | struct { int v[10]; } t[10]; |
337 | |
338 | // CHECK: store i32 316 |
339 | gi = OBJECT_SIZE_BUILTIN(&t[1].v[11], 0); |
340 | // CHECK: store i32 312 |
341 | gi = OBJECT_SIZE_BUILTIN(&t[1].v[12], 1); |
342 | // CHECK: store i32 308 |
343 | gi = OBJECT_SIZE_BUILTIN(&t[1].v[13], 2); |
344 | // CHECK: store i32 0 |
345 | gi = OBJECT_SIZE_BUILTIN(&t[1].v[14], 3); |
346 | } |
347 | |
348 | struct Test27IncompleteTy; |
349 | |
350 | // CHECK-LABEL: @test27 |
351 | void test27(struct Test27IncompleteTy *t) { |
352 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
353 | gi = OBJECT_SIZE_BUILTIN(t, 0); |
354 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
355 | gi = OBJECT_SIZE_BUILTIN(t, 1); |
356 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
357 | gi = OBJECT_SIZE_BUILTIN(t, 2); |
358 | // Note: this is currently fixed at 0 because LLVM doesn't have sufficient |
359 | // data to correctly handle type=3 |
360 | // CHECK: store i32 0 |
361 | gi = OBJECT_SIZE_BUILTIN(t, 3); |
362 | |
363 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
364 | gi = OBJECT_SIZE_BUILTIN(&test27, 0); |
365 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1 |
366 | gi = OBJECT_SIZE_BUILTIN(&test27, 1); |
367 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1 |
368 | gi = OBJECT_SIZE_BUILTIN(&test27, 2); |
369 | // Note: this is currently fixed at 0 because LLVM doesn't have sufficient |
370 | // data to correctly handle type=3 |
371 | // CHECK: store i32 0 |
372 | gi = OBJECT_SIZE_BUILTIN(&test27, 3); |
373 | } |
374 | |
375 | // The intent of this test is to ensure that OBJECT_SIZE_BUILTIN treats `&foo` |
376 | // and `(T*)&foo` identically, when used as the pointer argument. |
377 | // CHECK-LABEL: @test28 |
378 | void test28() { |
379 | struct { int v[10]; } t[10]; |
380 | |
381 | #define addCasts(s) ((char*)((short*)(s))) |
382 | // CHECK: store i32 360 |
383 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 0); |
384 | // CHECK: store i32 360 |
385 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 1); |
386 | // CHECK: store i32 360 |
387 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 2); |
388 | // CHECK: store i32 360 |
389 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 3); |
390 | |
391 | // CHECK: store i32 356 |
392 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 0); |
393 | // CHECK: store i32 36 |
394 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 1); |
395 | // CHECK: store i32 356 |
396 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 2); |
397 | // CHECK: store i32 36 |
398 | gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 3); |
399 | #undef addCasts |
400 | } |
401 | |
402 | struct DynStructVar { |
403 | char fst[16]; |
404 | char snd[]; |
405 | }; |
406 | |
407 | struct DynStruct0 { |
408 | char fst[16]; |
409 | char snd[0]; |
410 | }; |
411 | |
412 | struct DynStruct1 { |
413 | char fst[16]; |
414 | char snd[1]; |
415 | }; |
416 | |
417 | struct StaticStruct { |
418 | char fst[16]; |
419 | char snd[2]; |
420 | }; |
421 | |
422 | // CHECK-LABEL: @test29 |
423 | void test29(struct DynStructVar *dv, struct DynStruct0 *d0, |
424 | struct DynStruct1 *d1, struct StaticStruct *ss) { |
425 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
426 | gi = OBJECT_SIZE_BUILTIN(dv->snd, 0); |
427 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
428 | gi = OBJECT_SIZE_BUILTIN(dv->snd, 1); |
429 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
430 | gi = OBJECT_SIZE_BUILTIN(dv->snd, 2); |
431 | // CHECK: store i32 0 |
432 | gi = OBJECT_SIZE_BUILTIN(dv->snd, 3); |
433 | |
434 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
435 | gi = OBJECT_SIZE_BUILTIN(d0->snd, 0); |
436 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
437 | gi = OBJECT_SIZE_BUILTIN(d0->snd, 1); |
438 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
439 | gi = OBJECT_SIZE_BUILTIN(d0->snd, 2); |
440 | // CHECK: store i32 0 |
441 | gi = OBJECT_SIZE_BUILTIN(d0->snd, 3); |
442 | |
443 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
444 | gi = OBJECT_SIZE_BUILTIN(d1->snd, 0); |
445 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
446 | gi = OBJECT_SIZE_BUILTIN(d1->snd, 1); |
447 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
448 | gi = OBJECT_SIZE_BUILTIN(d1->snd, 2); |
449 | // CHECK: store i32 1 |
450 | gi = OBJECT_SIZE_BUILTIN(d1->snd, 3); |
451 | |
452 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
453 | gi = OBJECT_SIZE_BUILTIN(ss->snd, 0); |
454 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
455 | gi = OBJECT_SIZE_BUILTIN(ss->snd, 1); |
456 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
457 | gi = OBJECT_SIZE_BUILTIN(ss->snd, 2); |
458 | // CHECK: store i32 2 |
459 | gi = OBJECT_SIZE_BUILTIN(ss->snd, 3); |
460 | } |
461 | |
462 | // CHECK-LABEL: @test30 |
463 | void test30() { |
464 | struct { struct DynStruct1 fst, snd; } *nested; |
465 | |
466 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
467 | gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 0); |
468 | // CHECK: store i32 1 |
469 | gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 1); |
470 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
471 | gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 2); |
472 | // CHECK: store i32 1 |
473 | gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 3); |
474 | |
475 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
476 | gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 0); |
477 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
478 | gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 1); |
479 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
480 | gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 2); |
481 | // CHECK: store i32 1 |
482 | gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 3); |
483 | |
484 | union { struct DynStruct1 d1; char c[1]; } *u; |
485 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
486 | gi = OBJECT_SIZE_BUILTIN(u->c, 0); |
487 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
488 | gi = OBJECT_SIZE_BUILTIN(u->c, 1); |
489 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
490 | gi = OBJECT_SIZE_BUILTIN(u->c, 2); |
491 | // CHECK: store i32 1 |
492 | gi = OBJECT_SIZE_BUILTIN(u->c, 3); |
493 | |
494 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
495 | gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 0); |
496 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
497 | gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 1); |
498 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
499 | gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 2); |
500 | // CHECK: store i32 1 |
501 | gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 3); |
502 | } |
503 | |
504 | // CHECK-LABEL: @test31 |
505 | void test31() { |
506 | // Miscellaneous 'writing off the end' detection tests |
507 | struct DynStructVar *dsv; |
508 | struct DynStruct0 *ds0; |
509 | struct DynStruct1 *ds1; |
510 | struct StaticStruct *ss; |
511 | |
512 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
513 | gi = OBJECT_SIZE_BUILTIN(ds1[9].snd, 1); |
514 | |
515 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
516 | gi = OBJECT_SIZE_BUILTIN(&ss[9].snd[0], 1); |
517 | |
518 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
519 | gi = OBJECT_SIZE_BUILTIN(&ds1[9].snd[0], 1); |
520 | |
521 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
522 | gi = OBJECT_SIZE_BUILTIN(&ds0[9].snd[0], 1); |
523 | |
524 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
525 | gi = OBJECT_SIZE_BUILTIN(&dsv[9].snd[0], 1); |
526 | } |
527 | |
528 | // CHECK-LABEL: @PR30346 |
529 | void PR30346() { |
530 | struct sa_family_t {}; |
531 | struct sockaddr { |
532 | struct sa_family_t sa_family; |
533 | char sa_data[14]; |
534 | }; |
535 | |
536 | struct sockaddr *sa; |
537 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
538 | gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 0); |
539 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 |
540 | gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 1); |
541 | // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 |
542 | gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 2); |
543 | // CHECK: store i32 14 |
544 | gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 3); |
545 | } |
546 | |
547 | extern char incomplete_char_array[]; |
548 | // CHECK-LABEL: @incomplete_and_function_types |
549 | int incomplete_and_function_types() { |
550 | // CHECK: call i64 @llvm.objectsize.i64.p0i8 |
551 | gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 0); |
552 | // CHECK: call i64 @llvm.objectsize.i64.p0i8 |
553 | gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 1); |
554 | // CHECK: call i64 @llvm.objectsize.i64.p0i8 |
555 | gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 2); |
556 | // CHECK: store i32 0 |
557 | gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 3); |
558 | } |
559 | |
560 | // Flips between the pointer and lvalue evaluator a lot. |
561 | void deeply_nested() { |
562 | struct { |
563 | struct { |
564 | struct { |
565 | struct { |
566 | int e[2]; |
567 | char f; // Inhibit our writing-off-the-end check |
568 | } d[2]; |
569 | } c[2]; |
570 | } b[2]; |
571 | } *a; |
572 | |
573 | // CHECK: store i32 4 |
574 | gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 1); |
575 | // CHECK: store i32 4 |
576 | gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 3); |
577 | } |
578 | |