1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s
2 
3 namespace templates {
4 void *my_malloc(int N) __attribute__((alloc_size(1)));
5 void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));
6 
7 struct MyType {
8   int arr[4];
9 };
10 
11 template <typename T> int callMalloc();
12 
13 template <typename T, int N> int callCalloc();
14 
15 // CHECK-LABEL: define{{.*}} i32 @_ZN9templates6testItEv()
testIt()16 int 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
callMalloc()24 template <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
callCalloc()32 template <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 
39 namespace templated_alloc_size {
40 using 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.
45 template <typename T>
46 T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)));
47 
48 template <typename T>
49 T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));
50 
51 template <size_t N>
52 void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)));
53 
54 template <size_t N, size_t M>
55 void *dependent_calloc(size_t NT = N, size_t MT = M)
56     __attribute__((alloc_size(1, 2)));
57 
58 template <typename T, size_t M>
59 void *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
testIt()63 int 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.
75 namespace alloc_size_with_cleanups {
76 struct Foo {
77   ~Foo();
78 };
79 
80 void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2)));
81 
82 // CHECK-LABEL: define{{.*}} i32 @_ZN24alloc_size_with_cleanups6testItEv
testIt()83 int 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 
90 class C {
91 public:
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
callMemberMalloc()97 int callMemberMalloc() {
98   // CHECK: ret i32 16
99   return __builtin_object_size(C().my_malloc(16), 0);
100 }
101 
102 // CHECK-LABEL: define{{.*}} i32 @_Z16callMemberCallocv
callMemberCalloc()103 int callMemberCalloc() {
104   // CHECK: ret i32 32
105   return __builtin_object_size(C().my_calloc(16, 2), 0);
106 }
107