Clang Project

clang_source_code/test/CodeGen/object-size.c
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
15static char *__inline_strcpy_chk (char *dest, const char *src) {
16  return __builtin___strcpy_chk(dest, src, OBJECT_SIZE_BUILTIN(dest, 1));
17}
18
19char gbuf[63];
20char *gp;
21int gi, gj;
22
23// CHECK-LABEL: define void @test1
24void 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
30void 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
36void 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
42void 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
48void 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
55void 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
63void 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
73void 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
81void 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
88char **p;
89void 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
96void 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
103void 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
110void 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
117void 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
124void 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
131void 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
138void 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
150unsigned 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
158void 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
183void 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
197void 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
220void 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
260struct Test23Ty { int a; int t[10]; };
261
262// CHECK-LABEL: @test23
263void 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
296void 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
310void 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
335void 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
348struct Test27IncompleteTy;
349
350// CHECK-LABEL: @test27
351void 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
378void 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
402struct DynStructVar {
403  char fst[16];
404  char snd[];
405};
406
407struct DynStruct0 {
408  char fst[16];
409  char snd[0];
410};
411
412struct DynStruct1 {
413  char fst[16];
414  char snd[1];
415};
416
417struct StaticStruct {
418  char fst[16];
419  char snd[2];
420};
421
422// CHECK-LABEL: @test29
423void 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
463void 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
505void 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
529void 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
547extern char incomplete_char_array[];
548// CHECK-LABEL: @incomplete_and_function_types
549int 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.
561void 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