Clang Project

clang_source_code/test/CodeGenCXX/alloc-size.cpp
1// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s
2
3namespace templates {
4void *my_malloc(int N) __attribute__((alloc_size(1)));
5void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));
6
7struct MyType {
8  int arr[4];
9};
10
11template <typename T> int callMalloc();
12
13template <typename T, int N> int callCalloc();
14
15// CHECK-LABEL: define i32 @_ZN9templates6testItEv()
16int testIt() {
17  // CHECK: call i32 @_ZN9templates10callMallocINS_6MyTypeEEEiv
18  // CHECK: call i32 @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
19  return callMalloc<MyType>() + callCalloc<MyType, 4>();
20}
21
22// CHECK-LABEL: define linkonce_odr i32
23// @_ZN9templates10callMallocINS_6MyTypeEEEiv
24template <typename T> int callMalloc() {
25  static_assert(sizeof(T) == 16, "");
26  // CHECK: ret i32 16
27  return __builtin_object_size(my_malloc(sizeof(T)), 0);
28}
29
30// CHECK-LABEL: define linkonce_odr i32
31// @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
32template <typename T, int N> int callCalloc() {
33  static_assert(sizeof(T) * N == 64, "");
34  // CHECK: ret i32 64
35  return __builtin_object_size(my_malloc(sizeof(T) * N), 0);
36}
37}
38
39namespace templated_alloc_size {
40using size_t = unsigned long;
41
42// We don't need bodies for any of these, because they're only used in
43// __builtin_object_size, and that shouldn't need anything but a function
44// decl with alloc_size on it.
45template <typename T>
46T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)));
47
48template <typename T>
49T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));
50
51template <size_t N>
52void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)));
53
54template <size_t N, size_t M>
55void *dependent_calloc(size_t NT = N, size_t MT = M)
56    __attribute__((alloc_size(1, 2)));
57
58template <typename T, size_t M>
59void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M)
60    __attribute__((alloc_size(1, 2)));
61
62// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6testItEv
63int testIt() {
64  // 122 = 4 + 5*4 + 6 + 7*8 + 4*9
65  // CHECK: ret i32 122
66  return __builtin_object_size(my_malloc<int>(), 0) +
67         __builtin_object_size(my_calloc<int>(5), 0) +
68         __builtin_object_size(dependent_malloc<6>(), 0) +
69         __builtin_object_size(dependent_calloc<7, 8>(), 0) +
70         __builtin_object_size(dependent_calloc2<int, 9>(), 0);
71}
72} // namespace templated_alloc_size
73
74// Be sure that an ExprWithCleanups doesn't deter us.
75namespace alloc_size_with_cleanups {
76struct Foo {
77  ~Foo();
78};
79
80void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2)));
81
82// CHECK-LABEL: define i32 @_ZN24alloc_size_with_cleanups6testItEv
83int testIt() {
84  int *const p = (int *)my_malloc(Foo{}, 3);
85  // CHECK: ret i32 3
86  return __builtin_object_size(p, 0);
87}
88} // namespace alloc_size_with_cleanups
89
90class C {
91public:
92  void *my_malloc(int N) __attribute__((alloc_size(2)));
93  void *my_calloc(int N, int M) __attribute__((alloc_size(2, 3)));
94};
95
96// CHECK-LABEL: define i32 @_Z16callMemberMallocv
97int callMemberMalloc() {
98  // CHECK: ret i32 16
99  return __builtin_object_size(C().my_malloc(16), 0);
100}
101
102// CHECK-LABEL: define i32 @_Z16callMemberCallocv
103int callMemberCalloc() {
104  // CHECK: ret i32 32
105  return __builtin_object_size(C().my_calloc(16, 2), 0);
106}
107