reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s

namespace templates {
void *my_malloc(int N) __attribute__((alloc_size(1)));
void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));

struct MyType {
  int arr[4];
};

template <typename T> int callMalloc();

template <typename T, int N> int callCalloc();

// CHECK-LABEL: define i32 @_ZN9templates6testItEv()
int testIt() {
  // CHECK: call i32 @_ZN9templates10callMallocINS_6MyTypeEEEiv
  // CHECK: call i32 @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
  return callMalloc<MyType>() + callCalloc<MyType, 4>();
}

// CHECK-LABEL: define linkonce_odr i32
// @_ZN9templates10callMallocINS_6MyTypeEEEiv
template <typename T> int callMalloc() {
  static_assert(sizeof(T) == 16, "");
  // CHECK: ret i32 16
  return __builtin_object_size(my_malloc(sizeof(T)), 0);
}

// CHECK-LABEL: define linkonce_odr i32
// @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
template <typename T, int N> int callCalloc() {
  static_assert(sizeof(T) * N == 64, "");
  // CHECK: ret i32 64
  return __builtin_object_size(my_malloc(sizeof(T) * N), 0);
}
}

namespace templated_alloc_size {
using size_t = unsigned long;

// We don't need bodies for any of these, because they're only used in
// __builtin_object_size, and that shouldn't need anything but a function
// decl with alloc_size on it.
template <typename T>
T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)));

template <typename T>
T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));

template <size_t N>
void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)));

template <size_t N, size_t M>
void *dependent_calloc(size_t NT = N, size_t MT = M)
    __attribute__((alloc_size(1, 2)));

template <typename T, size_t M>
void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M)
    __attribute__((alloc_size(1, 2)));

// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6testItEv
int testIt() {
  // 122 = 4 + 5*4 + 6 + 7*8 + 4*9
  // CHECK: ret i32 122
  return __builtin_object_size(my_malloc<int>(), 0) +
         __builtin_object_size(my_calloc<int>(5), 0) +
         __builtin_object_size(dependent_malloc<6>(), 0) +
         __builtin_object_size(dependent_calloc<7, 8>(), 0) +
         __builtin_object_size(dependent_calloc2<int, 9>(), 0);
}
} // namespace templated_alloc_size

// Be sure that an ExprWithCleanups doesn't deter us.
namespace alloc_size_with_cleanups {
struct Foo {
  ~Foo();
};

void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2)));

// CHECK-LABEL: define i32 @_ZN24alloc_size_with_cleanups6testItEv
int testIt() {
  int *const p = (int *)my_malloc(Foo{}, 3);
  // CHECK: ret i32 3
  return __builtin_object_size(p, 0);
}
} // namespace alloc_size_with_cleanups

class C {
public:
  void *my_malloc(int N) __attribute__((alloc_size(2)));
  void *my_calloc(int N, int M) __attribute__((alloc_size(2, 3)));
};

// CHECK-LABEL: define i32 @_Z16callMemberMallocv
int callMemberMalloc() {
  // CHECK: ret i32 16
  return __builtin_object_size(C().my_malloc(16), 0);
}

// CHECK-LABEL: define i32 @_Z16callMemberCallocv
int callMemberCalloc() {
  // CHECK: ret i32 32
  return __builtin_object_size(C().my_calloc(16, 2), 0);
}