Files
clang-p2996/clang/test/CodeGenCXX/alloc-size.cpp
George Burgess IV e37633713d Add the alloc_size attribute to clang, attempt 2.
This is a recommit of r290149, which was reverted in r290169 due to msan
failures. msan was failing because we were calling
`isMostDerivedAnUnsizedArray` on an invalid designator, which caused us
to read uninitialized memory. To fix this, the logic of the caller of
said function was simplified, and we now have a `!Invalid` assert in
`isMostDerivedAnUnsizedArray`, so we can catch this particular bug more
easily in the future.

Fingers crossed that this patch sticks this time. :)

Original commit message:

This patch does three things:
- Gives us the alloc_size attribute in clang, which lets us infer the
  number of bytes handed back to us by malloc/realloc/calloc/any user
  functions that act in a similar manner.
- Teaches our constexpr evaluator that evaluating some `const` variables
  is OK sometimes. This is why we have a change in
  test/SemaCXX/constant-expression-cxx11.cpp and other seemingly
  unrelated tests. Richard Smith okay'ed this idea some time ago in
  person.
- Uniques some Blocks in CodeGen, which was reviewed separately at
  D26410. Lack of uniquing only really shows up as a problem when
  combined with our new eagerness in the face of const.

llvm-svn: 290297
2016-12-22 02:50:20 +00:00

73 lines
2.3 KiB
C++

// 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);
}
}