summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorGeorge Burgess IV <george.burgess.iv@gmail.com>2016-12-20 01:05:42 +0000
committerGeorge Burgess IV <george.burgess.iv@gmail.com>2016-12-20 01:05:42 +0000
commita747027bc6455cafcc380bd075ec98065f780494 (patch)
tree6e6cd58082dd2578586dc21bb6f9b7cc2a2ffee8 /clang/test
parent891cbcc093f112fb9f4ec839cd286364f4b0bcb0 (diff)
downloadbcm5719-llvm-a747027bc6455cafcc380bd075ec98065f780494.tar.gz
bcm5719-llvm-a747027bc6455cafcc380bd075ec98065f780494.zip
Add the alloc_size attribute to clang.
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. Differential Revision: https://reviews.llvm.org/D14274 llvm-svn: 290149
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGen/alloc-size.c352
-rw-r--r--clang/test/CodeGenCXX/alloc-size.cpp72
-rw-r--r--clang/test/CodeGenCXX/block-in-ctor-dtor.cpp2
-rw-r--r--clang/test/CodeGenCXX/global-init.cpp3
-rw-r--r--clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl24
-rw-r--r--clang/test/Sema/alloc-size.c23
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp4
7 files changed, 460 insertions, 20 deletions
diff --git a/clang/test/CodeGen/alloc-size.c b/clang/test/CodeGen/alloc-size.c
new file mode 100644
index 00000000000..1e503f0579c
--- /dev/null
+++ b/clang/test/CodeGen/alloc-size.c
@@ -0,0 +1,352 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s
+
+#define NULL ((void *)0)
+
+int gi;
+
+typedef unsigned long size_t;
+
+// CHECK-DAG-RE: define void @my_malloc({{.*}}) #[[MALLOC_ATTR_NUMBER:[0-9]+]]
+// N.B. LLVM's allocsize arguments are base-0, whereas ours are base-1 (for
+// compat with GCC)
+// CHECK-DAG-RE: attributes #[[MALLOC_ATTR_NUMBER]] = {.*allocsize(0).*}
+void *my_malloc(size_t) __attribute__((alloc_size(1)));
+
+// CHECK-DAG-RE: define void @my_calloc({{.*}}) #[[CALLOC_ATTR_NUMBER:[0-9]+]]
+// CHECK-DAG-RE: attributes #[[CALLOC_ATTR_NUMBER]] = {.*allocsize(0, 1).*}
+void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test1
+void test1() {
+ void *const vp = my_malloc(100);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 3);
+
+ void *const arr = my_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 3);
+
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 3);
+
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 3);
+
+ void *const zeroPtr = my_malloc(0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroPtr, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_malloc(0), 0);
+
+ void *const zeroArr1 = my_calloc(0, 1);
+ void *const zeroArr2 = my_calloc(1, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroArr1, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroArr2, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_calloc(1, 0), 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_calloc(0, 1), 0);
+}
+
+// CHECK-LABEL: @test2
+void test2() {
+ void *const vp = my_malloc(gi);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(vp, 0);
+
+ void *const arr1 = my_calloc(gi, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr1, 0);
+
+ void *const arr2 = my_calloc(1, gi);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr2, 0);
+}
+
+// CHECK-LABEL: @test3
+void test3() {
+ char *const buf = (char *)my_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 3);
+}
+
+struct Data {
+ int a;
+ int t[10];
+ char pad[3];
+ char end[1];
+};
+
+// CHECK-LABEL: @test5
+void test5() {
+ struct Data *const data = my_malloc(sizeof(*data));
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 0);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 1);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 2);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 3);
+
+ // CHECK: store i32 40
+ gi = __builtin_object_size(&data->t[1], 0);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&data->t[1], 1);
+ // CHECK: store i32 40
+ gi = __builtin_object_size(&data->t[1], 2);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&data->t[1], 3);
+
+ struct Data *const arr = my_calloc(sizeof(*data), 2);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 3);
+
+ // CHECK: store i32 88
+ gi = __builtin_object_size(&arr->t[1], 0);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&arr->t[1], 1);
+ // CHECK: store i32 88
+ gi = __builtin_object_size(&arr->t[1], 2);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&arr->t[1], 3);
+}
+
+// CHECK-LABEL: @test6
+void test6() {
+ // Things that would normally trigger conservative estimates don't need to do
+ // so when we know the source of the allocation.
+ struct Data *const data = my_malloc(sizeof(*data) + 10);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 0);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 1);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 2);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 3);
+
+ struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3);
+ // AFAICT, GCC treats malloc and calloc identically. So, we should do the
+ // same.
+ //
+ // Additionally, GCC ignores the initial array index when determining whether
+ // we're writing off the end of an alloc_size base. e.g.
+ // arr[0].end
+ // arr[1].end
+ // arr[2].end
+ // ...Are all considered "writing off the end", because there's no way to tell
+ // with high accuracy if the user meant "allocate a single N-byte `Data`",
+ // or "allocate M smaller `Data`s with extra padding".
+
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 0);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 1);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 2);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 3);
+
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 0);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 1);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 2);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 3);
+
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 0);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 1);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 2);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 3);
+
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 0);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 1);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 2);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 3);
+}
+
+// CHECK-LABEL: @test7
+void test7() {
+ struct Data *const data = my_malloc(sizeof(*data) + 5);
+ // CHECK: store i32 9
+ gi = __builtin_object_size(data->pad, 0);
+ // CHECK: store i32 3
+ gi = __builtin_object_size(data->pad, 1);
+ // CHECK: store i32 9
+ gi = __builtin_object_size(data->pad, 2);
+ // CHECK: store i32 3
+ gi = __builtin_object_size(data->pad, 3);
+}
+
+// CHECK-LABEL: @test8
+void test8() {
+ // Non-const pointers aren't currently supported.
+ void *buf = my_calloc(100, 5);
+ // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(buf, 3);
+}
+
+// CHECK-LABEL: @test9
+void test9() {
+ // Check to be sure that we unwrap things correctly.
+ short *const buf0 = (my_malloc(100));
+ short *const buf1 = (short*)(my_malloc(100));
+ short *const buf2 = ((short*)(my_malloc(100)));
+
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf0, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf1, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf2, 0);
+}
+
+// CHECK-LABEL: @test10
+void test10() {
+ // Yay overflow
+ short *const arr = my_calloc((size_t)-1 / 2 + 1, 2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(arr, 3);
+
+ // As an implementation detail, CharUnits can't handle numbers greater than or
+ // equal to 2**63. Realistically, this shouldn't be a problem, but we should
+ // be sure we don't emit crazy results for this case.
+ short *const buf = my_malloc((size_t)-1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(buf, 3);
+
+ short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(arr_big, 3);
+}
+
+void *my_tiny_malloc(char) __attribute__((alloc_size(1)));
+void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test11
+void test11() {
+ void *const vp = my_tiny_malloc(100);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 3);
+
+ // N.B. This causes char overflow, but not size_t overflow, so it should be
+ // supported.
+ void *const arr = my_tiny_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 3);
+}
+
+void *my_signed_malloc(long) __attribute__((alloc_size(1)));
+void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test12
+void test12() {
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_signed_malloc(100), 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_signed_calloc(100, 5), 0);
+
+ void *const vp = my_signed_malloc(-2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(vp, 0);
+ // N.B. These get lowered to -1 because the function calls may have
+ // side-effects, and we can't determine the objectsize.
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_malloc(-2), 0);
+
+ void *const arr1 = my_signed_calloc(-2, 1);
+ void *const arr2 = my_signed_calloc(1, -2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr1, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr2, 0);
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_calloc(1, -2), 0);
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_calloc(-2, 1), 0);
+}
diff --git a/clang/test/CodeGenCXX/alloc-size.cpp b/clang/test/CodeGenCXX/alloc-size.cpp
new file mode 100644
index 00000000000..e93e231b70e
--- /dev/null
+++ b/clang/test/CodeGenCXX/alloc-size.cpp
@@ -0,0 +1,72 @@
+// 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);
+}
+}
diff --git a/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp b/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
index 0dc0ab00437..0ec9db1db72 100644
--- a/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
+++ b/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
@@ -42,7 +42,5 @@ X::~X() {
// CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_
diff --git a/clang/test/CodeGenCXX/global-init.cpp b/clang/test/CodeGenCXX/global-init.cpp
index e806af9eacb..1e8694dd42a 100644
--- a/clang/test/CodeGenCXX/global-init.cpp
+++ b/clang/test/CodeGenCXX/global-init.cpp
@@ -18,9 +18,6 @@ struct D { ~D(); };
// CHECK: @__dso_handle = external global i8
// CHECK: @c = global %struct.C zeroinitializer, align 8
-// It's okay if we ever implement the IR-generation optimization to remove this.
-// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8], [7 x i8]*
-
// PR6205: The casts should not require global initializers
// CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C"
// CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* getelementptr inbounds (%"struct.PR5974::C", %"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0)
diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index 77ec747f873..9986f579957 100644
--- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -3,6 +3,8 @@
typedef void (^bl_t)(local void *);
+// N.B. The check here only exists to set BL_GLOBAL
+// COMMON: @block_G = {{.*}}bitcast ([[BL_GLOBAL:[^@]+@__block_literal_global(\.[0-9]+)?]]
const bl_t block_G = (bl_t) ^ (local void *a) {};
kernel void device_side_enqueue(global int *a, global int *b, int i) {
@@ -122,28 +124,24 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
},
4294967296L);
-
+ // The full type of these expressions are long (and repeated elsewhere), so we
+ // capture it as part of the regex for convenience and clarity.
+ // COMMON: store void ()* bitcast ([[BL_A:[^@]+@__block_literal_global.[0-9]+]] to void ()*), void ()** %block_A
void (^const block_A)(void) = ^{
return;
};
+
+ // COMMON: store void (i8 addrspace(2)*)* bitcast ([[BL_B:[^@]+@__block_literal_global.[0-9]+]] to void (i8 addrspace(2)*)*), void (i8 addrspace(2)*)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
- // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
- // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_A]] to i8*))
unsigned size = get_kernel_work_group_size(block_A);
- // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)** %block_B
- // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
- // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_B]] to i8*))
size = get_kernel_work_group_size(block_B);
- // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
- // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_A]] to i8*))
size = get_kernel_preferred_work_group_size_multiple(block_A);
- // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)* addrspace(1)* @block_G
- // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_GLOBAL]] to i8*))
size = get_kernel_preferred_work_group_size_multiple(block_G);
}
diff --git a/clang/test/Sema/alloc-size.c b/clang/test/Sema/alloc-size.c
new file mode 100644
index 00000000000..600ef6870e9
--- /dev/null
+++ b/clang/test/Sema/alloc-size.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 %s -verify
+
+void *fail1(int a) __attribute__((alloc_size)); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
+void *fail2(int a) __attribute__((alloc_size())); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
+
+void *fail3(int a) __attribute__((alloc_size(0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
+void *fail4(int a) __attribute__((alloc_size(2))); //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}
+
+void *fail5(int a, int b) __attribute__((alloc_size(0, 1))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
+void *fail6(int a, int b) __attribute__((alloc_size(3, 1))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
+
+void *fail7(int a, int b) __attribute__((alloc_size(1, 0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
+void *fail8(int a, int b) __attribute__((alloc_size(1, 3))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
+
+int fail9(int a) __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to return values that are pointers}}
+
+int fail10 __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to non-K&R-style functions}}
+
+void *fail11(void *a) __attribute__((alloc_size(1))); //expected-error{{'alloc_size' attribute argument may only refer to a function parameter of integer type}}
+
+void *fail12(int a) __attribute__((alloc_size("abc"))); //expected-error{{'alloc_size' attribute requires parameter 1 to be an integer constant}}
+void *fail12(int a) __attribute__((alloc_size(1, "abc"))); //expected-error{{'alloc_size' attribute requires parameter 2 to be an integer constant}}
+void *fail13(int a) __attribute__((alloc_size(1U<<31))); //expected-error{{integer constant expression evaluates to value 2147483648 that cannot be represented in a 32-bit signed integer type}}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 0b7528281ac..9ec8318b9e0 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1183,7 +1183,7 @@ constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant exp
constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}
struct T { int n; };
-const T t = { 42 }; // expected-note {{declared here}}
+const T t = { 42 };
constexpr int f(volatile int &&r) {
return r; // expected-note {{read of volatile-qualified type 'volatile int'}}
@@ -1195,7 +1195,7 @@ struct S {
int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}}
int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}}
int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}
- int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}
+ int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}}
};
}
OpenPOWER on IntegriCloud