George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 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() |
| 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 |
| 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 |
| 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 |
| 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 | } |