1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
2 
3 typedef unsigned long size_t;
4 
5 struct Foo {
6   int t[10];
7 };
8 
9 #define PS(N) __attribute__((pass_object_size(N)))
10 
11 int gi = 0;
12 
13 // CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64)
14 int ObjectSize0(void *const p PS(0)) {
15   // CHECK-NOT: @llvm.objectsize
16   return __builtin_object_size(p, 0);
17 }
18 
19 // CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64)
20 int ObjectSize1(void *const p PS(1)) {
21   // CHECK-NOT: @llvm.objectsize
22   return __builtin_object_size(p, 1);
23 }
24 
25 // CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64)
26 int ObjectSize2(void *const p PS(2)) {
27   // CHECK-NOT: @llvm.objectsize
28   return __builtin_object_size(p, 2);
29 }
30 
31 // CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64)
32 int ObjectSize3(void *const p PS(3)) {
33   // CHECK-NOT: @llvm.objectsize
34   return __builtin_object_size(p, 3);
35 }
36 
37 // CHECK-LABEL: define void @test1
test1()38 void test1() {
39   struct Foo t[10];
40 
41   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
42   gi = ObjectSize0(&t[1]);
43   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
44   gi = ObjectSize1(&t[1]);
45   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
46   gi = ObjectSize2(&t[1]);
47   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
48   gi = ObjectSize3(&t[1]);
49 
50   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
51   gi = ObjectSize0(&t[1].t[1]);
52   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
53   gi = ObjectSize1(&t[1].t[1]);
54   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
55   gi = ObjectSize2(&t[1].t[1]);
56   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
57   gi = ObjectSize3(&t[1].t[1]);
58 }
59 
60 // CHECK-LABEL: define void @test2
test2(struct Foo * t)61 void test2(struct Foo *t) {
62   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
63   gi = ObjectSize1(&t->t[1]);
64   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
65   gi = ObjectSize3(&t->t[1]);
66 }
67 
68 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
NoViableOverloadObjectSize0(void * const p)69 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
70   // CHECK: @llvm.objectsize
71   return __builtin_object_size(p, 0);
72 }
73 
74 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv
NoViableOverloadObjectSize1(void * const p)75 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
76   // CHECK: @llvm.objectsize
77   return __builtin_object_size(p, 1);
78 }
79 
80 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv
NoViableOverloadObjectSize2(void * const p)81 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
82   // CHECK: @llvm.objectsize
83   return __builtin_object_size(p, 2);
84 }
85 
86 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv
NoViableOverloadObjectSize3(void * const p)87 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
88   // CHECK-NOT: @llvm.objectsize
89   return __builtin_object_size(p, 3);
90 }
91 
92 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
93 // CHECK-NOT: @llvm.objectsize
94 int NoViableOverloadObjectSize0(void *const p PS(0))
95     __attribute__((overloadable)) {
96   return __builtin_object_size(p, 0);
97 }
98 
99 int NoViableOverloadObjectSize1(void *const p PS(1))
100     __attribute__((overloadable)) {
101   return __builtin_object_size(p, 1);
102 }
103 
104 int NoViableOverloadObjectSize2(void *const p PS(2))
105     __attribute__((overloadable)) {
106   return __builtin_object_size(p, 2);
107 }
108 
109 int NoViableOverloadObjectSize3(void *const p PS(3))
110     __attribute__((overloadable)) {
111   return __builtin_object_size(p, 3);
112 }
113 
114 const static int SHOULDNT_BE_CALLED = -100;
115 int NoViableOverloadObjectSize0(void *const p PS(0))
116     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
117   return SHOULDNT_BE_CALLED;
118 }
119 
120 int NoViableOverloadObjectSize1(void *const p PS(1))
121     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
122   return SHOULDNT_BE_CALLED;
123 }
124 
125 int NoViableOverloadObjectSize2(void *const p PS(2))
126     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
127   return SHOULDNT_BE_CALLED;
128 }
129 
130 int NoViableOverloadObjectSize3(void *const p PS(3))
131     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
132   return SHOULDNT_BE_CALLED;
133 }
134 
135 // CHECK-LABEL: define void @test3
test3()136 void test3() {
137   struct Foo t[10];
138 
139   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
140   gi = NoViableOverloadObjectSize0(&t[1]);
141   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
142   gi = NoViableOverloadObjectSize1(&t[1]);
143   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
144   gi = NoViableOverloadObjectSize2(&t[1]);
145   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
146   gi = NoViableOverloadObjectSize3(&t[1]);
147 
148   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
149   gi = NoViableOverloadObjectSize0(&t[1].t[1]);
150   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
151   gi = NoViableOverloadObjectSize1(&t[1].t[1]);
152   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
153   gi = NoViableOverloadObjectSize2(&t[1].t[1]);
154   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
155   gi = NoViableOverloadObjectSize3(&t[1].t[1]);
156 }
157 
158 // CHECK-LABEL: define void @test4
test4(struct Foo * t)159 void test4(struct Foo *t) {
160   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
161   gi = NoViableOverloadObjectSize0(&t[1]);
162   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
163   gi = NoViableOverloadObjectSize1(&t[1]);
164   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
165   gi = NoViableOverloadObjectSize2(&t[1]);
166   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
167   gi = NoViableOverloadObjectSize3(&t[1]);
168 
169   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
170   gi = NoViableOverloadObjectSize0(&t[1].t[1]);
171   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
172   gi = NoViableOverloadObjectSize1(&t[1].t[1]);
173   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
174   gi = NoViableOverloadObjectSize2(&t[1].t[1]);
175   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
176   gi = NoViableOverloadObjectSize3(&t[1].t[1]);
177 }
178 
test5()179 void test5() {
180   struct Foo t[10];
181 
182   int (*f)(void *) = &NoViableOverloadObjectSize0;
183   gi = f(&t[1]);
184 }
185 
186 // CHECK-LABEL: define i32 @IndirectObjectSize0
187 int IndirectObjectSize0(void *const p PS(0)) {
188   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
189   // CHECK-NOT: @llvm.objectsize
190   return ObjectSize0(p);
191 }
192 
193 // CHECK-LABEL: define i32 @IndirectObjectSize1
194 int IndirectObjectSize1(void *const p PS(1)) {
195   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
196   // CHECK-NOT: @llvm.objectsize
197   return ObjectSize1(p);
198 }
199 
200 // CHECK-LABEL: define i32 @IndirectObjectSize2
201 int IndirectObjectSize2(void *const p PS(2)) {
202   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
203   // CHECK-NOT: @llvm.objectsize
204   return ObjectSize2(p);
205 }
206 
207 // CHECK-LABEL: define i32 @IndirectObjectSize3
208 int IndirectObjectSize3(void *const p PS(3)) {
209   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
210   // CHECK-NOT: @llvm.objectsize
211   return ObjectSize3(p);
212 }
213 
214 int Overload0(void *, size_t, void *, size_t);
215 int OverloadNoSize(void *, void *);
216 
217 int OverloadedObjectSize(void *const p PS(0),
218                          void *const c PS(0))
219     __attribute__((overloadable)) __asm__("Overload0");
220 
221 int OverloadedObjectSize(void *const p, void *const c)
222     __attribute__((overloadable)) __asm__("OverloadNoSize");
223 
224 // CHECK-LABEL: define void @test6
test6()225 void test6() {
226   int known[10], *opaque;
227 
228   // CHECK: call i32 @"\01Overload0"
229   gi = OverloadedObjectSize(&known[0], &known[0]);
230 
231   // CHECK: call i32 @"\01Overload0"
232   gi = OverloadedObjectSize(&known[0], opaque);
233 
234   // CHECK: call i32 @"\01Overload0"
235   gi = OverloadedObjectSize(opaque, &known[0]);
236 
237   // CHECK: call i32 @"\01Overload0"
238   gi = OverloadedObjectSize(opaque, opaque);
239 }
240 
Identity(void * p,size_t i)241 int Identity(void *p, size_t i) { return i; }
242 
243 // CHECK-NOT: define void @AsmObjectSize
244 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
245 
246 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
247 
248 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
249 
250 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
251 
252 // CHECK-LABEL: define void @test7
test7()253 void test7() {
254   struct Foo t[10];
255 
256   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
257   gi = AsmObjectSize0(&t[1]);
258   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
259   gi = AsmObjectSize1(&t[1]);
260   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
261   gi = AsmObjectSize2(&t[1]);
262   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
263   gi = AsmObjectSize3(&t[1]);
264 
265   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
266   gi = AsmObjectSize0(&t[1].t[1]);
267   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
268   gi = AsmObjectSize1(&t[1].t[1]);
269   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
270   gi = AsmObjectSize2(&t[1].t[1]);
271   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
272   gi = AsmObjectSize3(&t[1].t[1]);
273 }
274 
275 // CHECK-LABEL: define void @test8
test8(struct Foo * t)276 void test8(struct Foo *t) {
277   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
278   gi = AsmObjectSize1(&t[1].t[1]);
279   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
280   gi = AsmObjectSize3(&t[1].t[1]);
281 }
282 
283 void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
284 void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
285 void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
286 void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
287 
288 // CHECK-LABEL: define void @test9
test9(void * const p)289 void test9(void *const p __attribute__((pass_object_size(0)))) {
290   // CHECK: @llvm.objectsize
291   DifferingObjectSize2(p);
292 
293   // CHECK-NOT: @llvm.objectsize
294   DifferingObjectSize0(p);
295   DifferingObjectSize1(p);
296 
297   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
298   DifferingObjectSize3(p);
299 }
300 
301 // CHECK-LABEL: define void @test10
test10(void * const p)302 void test10(void *const p __attribute__((pass_object_size(1)))) {
303   // CHECK: @llvm.objectsize
304   DifferingObjectSize2(p);
305   // CHECK: @llvm.objectsize
306   DifferingObjectSize0(p);
307 
308   // CHECK-NOT: @llvm.objectsize
309   DifferingObjectSize1(p);
310 
311   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
312   DifferingObjectSize3(p);
313 }
314 
315 // CHECK-LABEL: define void @test11
test11(void * const p)316 void test11(void *const p __attribute__((pass_object_size(2)))) {
317   // CHECK: @llvm.objectsize
318   DifferingObjectSize0(p);
319   // CHECK: @llvm.objectsize
320   DifferingObjectSize1(p);
321 
322   // CHECK-NOT: @llvm.objectsize
323   DifferingObjectSize2(p);
324 
325   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
326   DifferingObjectSize3(p);
327 }
328 
329 // CHECK-LABEL: define void @test12
test12(void * const p)330 void test12(void *const p __attribute__((pass_object_size(3)))) {
331   // CHECK: @llvm.objectsize
332   DifferingObjectSize0(p);
333   // CHECK: @llvm.objectsize
334   DifferingObjectSize1(p);
335 
336   // CHECK-NOT: @llvm.objectsize
337   DifferingObjectSize2(p);
338   DifferingObjectSize3(p);
339 }
340 
341 // CHECK-LABEL: define void @test13
test13()342 void test13() {
343   // Ensuring that we don't lower objectsize if the expression has side-effects
344   char c[10];
345   char *p = c;
346 
347   // CHECK: @llvm.objectsize
348   ObjectSize0(p);
349 
350   // CHECK-NOT: @llvm.objectsize
351   ObjectSize0(++p);
352   ObjectSize0(p++);
353 }
354 
355 // There was a bug where variadic functions with pass_object_size would cause
356 // problems in the form of failed assertions.
my_sprintf(char * const c,...)357 void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
358 
359 // CHECK-LABEL: define void @test14
test14(char * c)360 void test14(char *c) {
361   // CHECK: @llvm.objectsize
362   // CHECK: call void (i8*, i64, ...) @my_sprintf
363   my_sprintf(c);
364 
365   // CHECK: @llvm.objectsize
366   // CHECK: call void (i8*, i64, ...) @my_sprintf
367   my_sprintf(c, 1, 2, 3);
368 }
369