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
__inline_strcpy_chk(char * dest,const char * src)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
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
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
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
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
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
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
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
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
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;
test10()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
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
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
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
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
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
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
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
test18(int cond)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
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
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
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
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
test23(struct Test23Ty * p)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
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
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
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
test27(struct Test27IncompleteTy * t)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
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
test29(struct DynStructVar * dv,struct DynStruct0 * d0,struct DynStruct1 * d1,struct StaticStruct * ss)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
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
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
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
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.
deeply_nested()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