xref: /llvm-project/clang/test/CodeGen/object-size.c (revision 12f78e740c5419f7d1fbcf8f2106e7a40cd1d6f7)
1 // RUN: %clang_cc1 -no-enable-noundef-analysis           -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s
2 // RUN: %clang_cc1 -no-enable-noundef-analysis -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(void) {
25   // CHECK:     = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 4), ptr @.str, i64 59)
26   strcpy(&gbuf[4], "Hi there");
27 }
28 
29 // CHECK-LABEL: define{{.*}} void @test2
30 void test2(void) {
31   // CHECK:     = call ptr @__strcpy_chk(ptr @gbuf, ptr @.str, i64 63)
32   strcpy(gbuf, "Hi there");
33 }
34 
35 // CHECK-LABEL: define{{.*}} void @test3
36 void test3(void) {
37   // CHECK:     = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 100), ptr @.str, i64 0)
38   strcpy(&gbuf[100], "Hi there");
39 }
40 
41 // CHECK-LABEL: define{{.*}} void @test4
42 void test4(void) {
43   // CHECK:     = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 -1), ptr @.str, i64 0)
44   strcpy((char*)(void*)&gbuf[-1], "Hi there");
45 }
46 
47 // CHECK-LABEL: define{{.*}} void @test5
48 void test5(void) {
49   // CHECK:     = load ptr, ptr @gp
50   // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
51   strcpy(gp, "Hi there");
52 }
53 
54 // CHECK-LABEL: define{{.*}} void @test6
55 void test6(void) {
56   char buf[57];
57 
58   // CHECK:       = call ptr @__strcpy_chk(ptr %{{.*}}, ptr @.str, i64 53)
59   strcpy(&buf[4], "Hi there");
60 }
61 
62 // CHECK-LABEL: define{{.*}} void @test7
63 void test7(void) {
64   int i;
65   // Ensure we only evaluate the side-effect once.
66   // CHECK:     = add
67   // CHECK-NOT: = add
68   // CHECK:     = call ptr @__strcpy_chk(ptr @gbuf, ptr @.str, i64 63)
69   strcpy((++i, gbuf), "Hi there");
70 }
71 
72 // CHECK-LABEL: define{{.*}} void @test8
73 void test8(void) {
74   char *buf[50];
75   // CHECK-NOT:   __strcpy_chk
76   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
77   strcpy(buf[++gi], "Hi there");
78 }
79 
80 // CHECK-LABEL: define{{.*}} void @test9
81 void test9(void) {
82   // CHECK-NOT:   __strcpy_chk
83   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
84   strcpy((char *)((++gi) + gj), "Hi there");
85 }
86 
87 // CHECK-LABEL: define{{.*}} void @test10
88 char **p;
89 void test10(void) {
90   // CHECK-NOT:   __strcpy_chk
91   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
92   strcpy(*(++p), "Hi there");
93 }
94 
95 // CHECK-LABEL: define{{.*}} void @test11
96 void test11(void) {
97   // CHECK-NOT:   __strcpy_chk
98   // CHECK:       = call ptr @__inline_strcpy_chk(ptr @gbuf, ptr @.str)
99   strcpy(gp = gbuf, "Hi there");
100 }
101 
102 // CHECK-LABEL: define{{.*}} void @test12
103 void test12(void) {
104   // CHECK-NOT:   __strcpy_chk
105   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
106   strcpy(++gp, "Hi there");
107 }
108 
109 // CHECK-LABEL: define{{.*}} void @test13
110 void test13(void) {
111   // CHECK-NOT:   __strcpy_chk
112   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
113   strcpy(gp++, "Hi there");
114 }
115 
116 // CHECK-LABEL: define{{.*}} void @test14
117 void test14(void) {
118   // CHECK-NOT:   __strcpy_chk
119   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
120   strcpy(--gp, "Hi there");
121 }
122 
123 // CHECK-LABEL: define{{.*}} void @test15
124 void test15(void) {
125   // CHECK-NOT:   __strcpy_chk
126   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{..*}}, ptr @.str)
127   strcpy(gp--, "Hi there");
128 }
129 
130 // CHECK-LABEL: define{{.*}} void @test16
131 void test16(void) {
132   // CHECK-NOT:   __strcpy_chk
133   // CHECK:       = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str)
134   strcpy(gp += 1, "Hi there");
135 }
136 
137 // CHECK-LABEL: @test17
138 void test17(void) {
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 ptr
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(void) {
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(void) {
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(void) {
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(void) {
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.p0(ptr %{{.*}}, i1 false, i1 true, i1
265   gi = OBJECT_SIZE_BUILTIN(p, 0);
266   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
267   gi = OBJECT_SIZE_BUILTIN(p, 1);
268   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
285   gi = OBJECT_SIZE_BUILTIN(&p->t[5], 0);
286   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
287   gi = OBJECT_SIZE_BUILTIN(&p->t[5], 1);
288   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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(void) {
297   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
298   gi = OBJECT_SIZE_BUILTIN((void*)0, 0);
299   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
300   gi = OBJECT_SIZE_BUILTIN((void*)0, 1);
301   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, 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(void) {
311   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
312   gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 0);
313   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
314   gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 1);
315   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, 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.p0(ptr {{.*}}, i1 false, i1 true, i1
323   gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 0);
324   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
325   gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 1);
326   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, 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(void) {
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.p0(ptr %{{.*}}, i1 false, i1 true, i1
353   gi = OBJECT_SIZE_BUILTIN(t, 0);
354   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
355   gi = OBJECT_SIZE_BUILTIN(t, 1);
356   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr {{.*}}, i1 false, i1 true, i1
364   gi = OBJECT_SIZE_BUILTIN(&test27, 0);
365   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
366   gi = OBJECT_SIZE_BUILTIN(&test27, 1);
367   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, 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(void) {
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.p0(ptr %{{.*}}, i1 false, i1 true, i1
426   gi = OBJECT_SIZE_BUILTIN(dv->snd, 0);
427   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
428   gi = OBJECT_SIZE_BUILTIN(dv->snd, 1);
429   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
435   gi = OBJECT_SIZE_BUILTIN(d0->snd, 0);
436   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
437   gi = OBJECT_SIZE_BUILTIN(d0->snd, 1);
438   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
444   gi = OBJECT_SIZE_BUILTIN(d1->snd, 0);
445   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
446   gi = OBJECT_SIZE_BUILTIN(d1->snd, 1);
447   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
453   gi = OBJECT_SIZE_BUILTIN(ss->snd, 0);
454   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
455   gi = OBJECT_SIZE_BUILTIN(ss->snd, 1);
456   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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(void) {
464   struct { struct DynStruct1 fst, snd; } *nested;
465 
466   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
476   gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 0);
477   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
478   gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 1);
479   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
486   gi = OBJECT_SIZE_BUILTIN(u->c, 0);
487   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
488   gi = OBJECT_SIZE_BUILTIN(u->c, 1);
489   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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.p0(ptr %{{.*}}, i1 false, i1 true, i1
495   gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 0);
496   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
497   gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 1);
498   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, 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(void) {
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.p0(ptr %{{.*}}, i1 false, i1 true, i1
513   gi = OBJECT_SIZE_BUILTIN(ds1[9].snd, 1);
514 
515   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
516   gi = OBJECT_SIZE_BUILTIN(&ss[9].snd[0], 1);
517 
518   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
519   gi = OBJECT_SIZE_BUILTIN(&ds1[9].snd[0], 1);
520 
521   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
522   gi = OBJECT_SIZE_BUILTIN(&ds0[9].snd[0], 1);
523 
524   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
525   gi = OBJECT_SIZE_BUILTIN(&dsv[9].snd[0], 1);
526 }
527 
528 // CHECK-LABEL: @test32
529 static struct DynStructVar D32 = {
530   .fst = {},
531   .snd = { 0, 1, 2, },
532 };
533 unsigned long test32(void) {
534   // CHECK: ret i64 19
535   return OBJECT_SIZE_BUILTIN(&D32, 1);
536 }
537 // CHECK-LABEL: @test33
538 static struct DynStructVar D33 = {
539   .fst = {},
540   .snd = {},
541 };
542 unsigned long test33(void) {
543   // CHECK: ret i64 16
544   return OBJECT_SIZE_BUILTIN(&D33, 1);
545 }
546 // CHECK-LABEL: @test34
547 static struct DynStructVar D34 = {
548   .fst = {},
549 };
550 unsigned long test34(void) {
551   // CHECK: ret i64 16
552   return OBJECT_SIZE_BUILTIN(&D34, 1);
553 }
554 // CHECK-LABEL: @test35
555 unsigned long test35(void) {
556   // CHECK: ret i64 16
557   return OBJECT_SIZE_BUILTIN(&(struct DynStructVar){}, 1);
558 }
559 extern void *memset (void *s, int c, unsigned long n);
560 void test36(void) {
561   struct DynStructVar D;
562   // FORTIFY will check the object size of D. Test this doesn't assert when
563   // given a struct with a flexible array member that lacks an initializer.
564   memset(&D, 0, sizeof(D));
565 }
566 // CHECK-LABEL: @test37
567 struct Z { struct A { int x, y[]; } z; int a; int b[]; };
568 static struct Z my_z = { .b = {1,2,3} };
569 unsigned long test37 (void) {
570   // CHECK: ret i64 4
571   return OBJECT_SIZE_BUILTIN(&my_z.z, 1);
572 }
573 
574 // CHECK-LABEL: @PR30346
575 void PR30346(void) {
576   struct sa_family_t {};
577   struct sockaddr {
578     struct sa_family_t sa_family;
579     char sa_data[14];
580   };
581 
582   struct sockaddr *sa;
583   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
584   gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 0);
585   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
586   gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 1);
587   // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
588   gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 2);
589   // CHECK: store i32 14
590   gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 3);
591 }
592 
593 extern char incomplete_char_array[];
594 // CHECK-LABEL: @incomplete_and_function_types
595 void incomplete_and_function_types(void) {
596   // CHECK: call i64 @llvm.objectsize.i64.p0
597   gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 0);
598   // CHECK: call i64 @llvm.objectsize.i64.p0
599   gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 1);
600   // CHECK: call i64 @llvm.objectsize.i64.p0
601   gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 2);
602   // CHECK: store i32 0
603   gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 3);
604 }
605 
606 // Flips between the pointer and lvalue evaluator a lot.
607 void deeply_nested(void) {
608   struct {
609     struct {
610       struct {
611         struct {
612           int e[2];
613           char f; // Inhibit our writing-off-the-end check
614         } d[2];
615       } c[2];
616     } b[2];
617   } *a;
618 
619   // CHECK: store i32 4
620   gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 1);
621   // CHECK: store i32 4
622   gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 3);
623 }
624