Clang Project

clang_source_code/test/CodeGen/alloc-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#ifdef DYNAMIC
5#define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size
6#else
7#define OBJECT_SIZE_BUILTIN __builtin_object_size
8#endif
9
10#define NULL ((void *)0)
11
12int gi;
13
14typedef unsigned long size_t;
15
16// CHECK-DAG-RE: define void @my_malloc({{.*}}) #[[MALLOC_ATTR_NUMBER:[0-9]+]]
17// N.B. LLVM's allocsize arguments are base-0, whereas ours are base-1 (for
18// compat with GCC)
19// CHECK-DAG-RE: attributes #[[MALLOC_ATTR_NUMBER]] = {.*allocsize(0).*}
20void *my_malloc(size_t) __attribute__((alloc_size(1)));
21
22// CHECK-DAG-RE: define void @my_calloc({{.*}}) #[[CALLOC_ATTR_NUMBER:[0-9]+]]
23// CHECK-DAG-RE: attributes #[[CALLOC_ATTR_NUMBER]] = {.*allocsize(0, 1).*}
24void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2)));
25
26// CHECK-LABEL: @test1
27void test1() {
28  void *const vp = my_malloc(100);
29  // CHECK: store i32 100
30  gi = OBJECT_SIZE_BUILTIN(vp, 0);
31  // CHECK: store i32 100
32  gi = OBJECT_SIZE_BUILTIN(vp, 1);
33  // CHECK: store i32 100
34  gi = OBJECT_SIZE_BUILTIN(vp, 2);
35  // CHECK: store i32 100
36  gi = OBJECT_SIZE_BUILTIN(vp, 3);
37
38  void *const arr = my_calloc(100, 5);
39  // CHECK: store i32 500
40  gi = OBJECT_SIZE_BUILTIN(arr, 0);
41  // CHECK: store i32 500
42  gi = OBJECT_SIZE_BUILTIN(arr, 1);
43  // CHECK: store i32 500
44  gi = OBJECT_SIZE_BUILTIN(arr, 2);
45  // CHECK: store i32 500
46  gi = OBJECT_SIZE_BUILTIN(arr, 3);
47
48  // CHECK: store i32 100
49  gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 0);
50  // CHECK: store i32 100
51  gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 1);
52  // CHECK: store i32 100
53  gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 2);
54  // CHECK: store i32 100
55  gi = OBJECT_SIZE_BUILTIN(my_malloc(100), 3);
56
57  // CHECK: store i32 500
58  gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 0);
59  // CHECK: store i32 500
60  gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 1);
61  // CHECK: store i32 500
62  gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 2);
63  // CHECK: store i32 500
64  gi = OBJECT_SIZE_BUILTIN(my_calloc(100, 5), 3);
65
66  void *const zeroPtr = my_malloc(0);
67  // CHECK: store i32 0
68  gi = OBJECT_SIZE_BUILTIN(zeroPtr, 0);
69  // CHECK: store i32 0
70  gi = OBJECT_SIZE_BUILTIN(my_malloc(0), 0);
71
72  void *const zeroArr1 = my_calloc(0, 1);
73  void *const zeroArr2 = my_calloc(1, 0);
74  // CHECK: store i32 0
75  gi = OBJECT_SIZE_BUILTIN(zeroArr1, 0);
76  // CHECK: store i32 0
77  gi = OBJECT_SIZE_BUILTIN(zeroArr2, 0);
78  // CHECK: store i32 0
79  gi = OBJECT_SIZE_BUILTIN(my_calloc(1, 0), 0);
80  // CHECK: store i32 0
81  gi = OBJECT_SIZE_BUILTIN(my_calloc(0, 1), 0);
82}
83
84// CHECK-LABEL: @test2
85void test2() {
86  void *const vp = my_malloc(gi);
87  // CHECK: @llvm.objectsize
88  gi = OBJECT_SIZE_BUILTIN(vp, 0);
89
90  void *const arr1 = my_calloc(gi, 1);
91  // CHECK: @llvm.objectsize
92  gi = OBJECT_SIZE_BUILTIN(arr1, 0);
93
94  void *const arr2 = my_calloc(1, gi);
95  // CHECK: @llvm.objectsize
96  gi = OBJECT_SIZE_BUILTIN(arr2, 0);
97}
98
99// CHECK-LABEL: @test3
100void test3() {
101  char *const buf = (char *)my_calloc(100, 5);
102  // CHECK: store i32 500
103  gi = OBJECT_SIZE_BUILTIN(buf, 0);
104  // CHECK: store i32 500
105  gi = OBJECT_SIZE_BUILTIN(buf, 1);
106  // CHECK: store i32 500
107  gi = OBJECT_SIZE_BUILTIN(buf, 2);
108  // CHECK: store i32 500
109  gi = OBJECT_SIZE_BUILTIN(buf, 3);
110}
111
112struct Data {
113  int a;
114  int t[10];
115  char pad[3];
116  char end[1];
117};
118
119// CHECK-LABEL: @test5
120void test5() {
121  struct Data *const data = my_malloc(sizeof(*data));
122  // CHECK: store i32 48
123  gi = OBJECT_SIZE_BUILTIN(data, 0);
124  // CHECK: store i32 48
125  gi = OBJECT_SIZE_BUILTIN(data, 1);
126  // CHECK: store i32 48
127  gi = OBJECT_SIZE_BUILTIN(data, 2);
128  // CHECK: store i32 48
129  gi = OBJECT_SIZE_BUILTIN(data, 3);
130
131  // CHECK: store i32 40
132  gi = OBJECT_SIZE_BUILTIN(&data->t[1], 0);
133  // CHECK: store i32 36
134  gi = OBJECT_SIZE_BUILTIN(&data->t[1], 1);
135  // CHECK: store i32 40
136  gi = OBJECT_SIZE_BUILTIN(&data->t[1], 2);
137  // CHECK: store i32 36
138  gi = OBJECT_SIZE_BUILTIN(&data->t[1], 3);
139
140  struct Data *const arr = my_calloc(sizeof(*data), 2);
141  // CHECK: store i32 96
142  gi = OBJECT_SIZE_BUILTIN(arr, 0);
143  // CHECK: store i32 96
144  gi = OBJECT_SIZE_BUILTIN(arr, 1);
145  // CHECK: store i32 96
146  gi = OBJECT_SIZE_BUILTIN(arr, 2);
147  // CHECK: store i32 96
148  gi = OBJECT_SIZE_BUILTIN(arr, 3);
149
150  // CHECK: store i32 88
151  gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 0);
152  // CHECK: store i32 36
153  gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 1);
154  // CHECK: store i32 88
155  gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 2);
156  // CHECK: store i32 36
157  gi = OBJECT_SIZE_BUILTIN(&arr->t[1], 3);
158}
159
160// CHECK-LABEL: @test6
161void test6() {
162  // Things that would normally trigger conservative estimates don't need to do
163  // so when we know the source of the allocation.
164  struct Data *const data = my_malloc(sizeof(*data) + 10);
165  // CHECK: store i32 11
166  gi = OBJECT_SIZE_BUILTIN(data->end, 0);
167  // CHECK: store i32 11
168  gi = OBJECT_SIZE_BUILTIN(data->end, 1);
169  // CHECK: store i32 11
170  gi = OBJECT_SIZE_BUILTIN(data->end, 2);
171  // CHECK: store i32 11
172  gi = OBJECT_SIZE_BUILTIN(data->end, 3);
173
174  struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3);
175  // AFAICT, GCC treats malloc and calloc identically. So, we should do the
176  // same.
177  //
178  // Additionally, GCC ignores the initial array index when determining whether
179  // we're writing off the end of an alloc_size base. e.g.
180  //   arr[0].end
181  //   arr[1].end
182  //   arr[2].end
183  // ...Are all considered "writing off the end", because there's no way to tell
184  // with high accuracy if the user meant "allocate a single N-byte `Data`",
185  // or "allocate M smaller `Data`s with extra padding".
186
187  // CHECK: store i32 112
188  gi = OBJECT_SIZE_BUILTIN(arr->end, 0);
189  // CHECK: store i32 112
190  gi = OBJECT_SIZE_BUILTIN(arr->end, 1);
191  // CHECK: store i32 112
192  gi = OBJECT_SIZE_BUILTIN(arr->end, 2);
193  // CHECK: store i32 112
194  gi = OBJECT_SIZE_BUILTIN(arr->end, 3);
195
196  // CHECK: store i32 112
197  gi = OBJECT_SIZE_BUILTIN(arr[0].end, 0);
198  // CHECK: store i32 112
199  gi = OBJECT_SIZE_BUILTIN(arr[0].end, 1);
200  // CHECK: store i32 112
201  gi = OBJECT_SIZE_BUILTIN(arr[0].end, 2);
202  // CHECK: store i32 112
203  gi = OBJECT_SIZE_BUILTIN(arr[0].end, 3);
204
205  // CHECK: store i32 64
206  gi = OBJECT_SIZE_BUILTIN(arr[1].end, 0);
207  // CHECK: store i32 64
208  gi = OBJECT_SIZE_BUILTIN(arr[1].end, 1);
209  // CHECK: store i32 64
210  gi = OBJECT_SIZE_BUILTIN(arr[1].end, 2);
211  // CHECK: store i32 64
212  gi = OBJECT_SIZE_BUILTIN(arr[1].end, 3);
213
214  // CHECK: store i32 16
215  gi = OBJECT_SIZE_BUILTIN(arr[2].end, 0);
216  // CHECK: store i32 16
217  gi = OBJECT_SIZE_BUILTIN(arr[2].end, 1);
218  // CHECK: store i32 16
219  gi = OBJECT_SIZE_BUILTIN(arr[2].end, 2);
220  // CHECK: store i32 16
221  gi = OBJECT_SIZE_BUILTIN(arr[2].end, 3);
222}
223
224// CHECK-LABEL: @test7
225void test7() {
226  struct Data *const data = my_malloc(sizeof(*data) + 5);
227  // CHECK: store i32 9
228  gi = OBJECT_SIZE_BUILTIN(data->pad, 0);
229  // CHECK: store i32 3
230  gi = OBJECT_SIZE_BUILTIN(data->pad, 1);
231  // CHECK: store i32 9
232  gi = OBJECT_SIZE_BUILTIN(data->pad, 2);
233  // CHECK: store i32 3
234  gi = OBJECT_SIZE_BUILTIN(data->pad, 3);
235}
236
237// CHECK-LABEL: @test8
238void test8() {
239  // Non-const pointers aren't currently supported.
240  void *buf = my_calloc(100, 5);
241  // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
242  gi = OBJECT_SIZE_BUILTIN(buf, 0);
243  // CHECK: @llvm.objectsize
244  gi = OBJECT_SIZE_BUILTIN(buf, 1);
245  // CHECK: @llvm.objectsize
246  gi = OBJECT_SIZE_BUILTIN(buf, 2);
247  // CHECK: store i32 0
248  gi = OBJECT_SIZE_BUILTIN(buf, 3);
249}
250
251// CHECK-LABEL: @test9
252void test9() {
253  // Check to be sure that we unwrap things correctly.
254  short *const buf0 = (my_malloc(100));
255  short *const buf1 = (short*)(my_malloc(100));
256  short *const buf2 = ((short*)(my_malloc(100)));
257
258  // CHECK: store i32 100
259  gi = OBJECT_SIZE_BUILTIN(buf0, 0);
260  // CHECK: store i32 100
261  gi = OBJECT_SIZE_BUILTIN(buf1, 0);
262  // CHECK: store i32 100
263  gi = OBJECT_SIZE_BUILTIN(buf2, 0);
264}
265
266// CHECK-LABEL: @test10
267void test10() {
268  // Yay overflow
269  short *const arr = my_calloc((size_t)-1 / 2 + 1, 2);
270  // CHECK: @llvm.objectsize
271  gi = OBJECT_SIZE_BUILTIN(arr, 0);
272  // CHECK: @llvm.objectsize
273  gi = OBJECT_SIZE_BUILTIN(arr, 1);
274  // CHECK: @llvm.objectsize
275  gi = OBJECT_SIZE_BUILTIN(arr, 2);
276  // CHECK: store i32 0
277  gi = OBJECT_SIZE_BUILTIN(arr, 3);
278
279  // As an implementation detail, CharUnits can't handle numbers greater than or
280  // equal to 2**63. Realistically, this shouldn't be a problem, but we should
281  // be sure we don't emit crazy results for this case.
282  short *const buf = my_malloc((size_t)-1);
283  // CHECK: @llvm.objectsize
284  gi = OBJECT_SIZE_BUILTIN(buf, 0);
285  // CHECK: @llvm.objectsize
286  gi = OBJECT_SIZE_BUILTIN(buf, 1);
287  // CHECK: @llvm.objectsize
288  gi = OBJECT_SIZE_BUILTIN(buf, 2);
289  // CHECK: store i32 0
290  gi = OBJECT_SIZE_BUILTIN(buf, 3);
291
292  short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2);
293  // CHECK: @llvm.objectsize
294  gi = OBJECT_SIZE_BUILTIN(arr_big, 0);
295  // CHECK: @llvm.objectsize
296  gi = OBJECT_SIZE_BUILTIN(arr_big, 1);
297  // CHECK: @llvm.objectsize
298  gi = OBJECT_SIZE_BUILTIN(arr_big, 2);
299  // CHECK: store i32 0
300  gi = OBJECT_SIZE_BUILTIN(arr_big, 3);
301}
302
303void *my_tiny_malloc(char) __attribute__((alloc_size(1)));
304void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2)));
305
306// CHECK-LABEL: @test11
307void test11() {
308  void *const vp = my_tiny_malloc(100);
309  // CHECK: store i32 100
310  gi = OBJECT_SIZE_BUILTIN(vp, 0);
311  // CHECK: store i32 100
312  gi = OBJECT_SIZE_BUILTIN(vp, 1);
313  // CHECK: store i32 100
314  gi = OBJECT_SIZE_BUILTIN(vp, 2);
315  // CHECK: store i32 100
316  gi = OBJECT_SIZE_BUILTIN(vp, 3);
317
318  // N.B. This causes char overflow, but not size_t overflow, so it should be
319  // supported.
320  void *const arr = my_tiny_calloc(100, 5);
321  // CHECK: store i32 500
322  gi = OBJECT_SIZE_BUILTIN(arr, 0);
323  // CHECK: store i32 500
324  gi = OBJECT_SIZE_BUILTIN(arr, 1);
325  // CHECK: store i32 500
326  gi = OBJECT_SIZE_BUILTIN(arr, 2);
327  // CHECK: store i32 500
328  gi = OBJECT_SIZE_BUILTIN(arr, 3);
329}
330
331void *my_signed_malloc(long) __attribute__((alloc_size(1)));
332void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2)));
333
334// CHECK-LABEL: @test12
335void test12() {
336  // CHECK: store i32 100
337  gi = OBJECT_SIZE_BUILTIN(my_signed_malloc(100), 0);
338  // CHECK: store i32 500
339  gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(100, 5), 0);
340
341  void *const vp = my_signed_malloc(-2);
342  // CHECK: @llvm.objectsize
343  gi = OBJECT_SIZE_BUILTIN(vp, 0);
344  // N.B. These get lowered to -1 because the function calls may have
345  // side-effects, and we can't determine the objectsize.
346  // CHECK: store i32 -1
347  gi = OBJECT_SIZE_BUILTIN(my_signed_malloc(-2), 0);
348
349  void *const arr1 = my_signed_calloc(-2, 1);
350  void *const arr2 = my_signed_calloc(1, -2);
351  // CHECK: @llvm.objectsize
352  gi = OBJECT_SIZE_BUILTIN(arr1, 0);
353  // CHECK: @llvm.objectsize
354  gi = OBJECT_SIZE_BUILTIN(arr2, 0);
355  // CHECK: store i32 -1
356  gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(1, -2), 0);
357  // CHECK: store i32 -1
358  gi = OBJECT_SIZE_BUILTIN(my_signed_calloc(-2, 1), 0);
359}
360