diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/alloc-align-attr.c | 101 | ||||
-rw-r--r-- | clang/test/Sema/alloc-align-attr.c | 19 | ||||
-rw-r--r-- | clang/test/SemaCXX/alloc-align-attr.cpp | 40 |
3 files changed, 160 insertions, 0 deletions
diff --git a/clang/test/CodeGen/alloc-align-attr.c b/clang/test/CodeGen/alloc-align-attr.c new file mode 100644 index 00000000000..b7cfcf76d45 --- /dev/null +++ b/clang/test/CodeGen/alloc-align-attr.c @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +__INT32_TYPE__*m1(__INT32_TYPE__ i) __attribute__((alloc_align(1))); + +// Condition where parameter to m1 is not size_t. +__INT32_TYPE__ test1(__INT32_TYPE__ a) { +// CHECK: define i32 @test1 + return *m1(a); +// CHECK: call i32* @m1(i32 [[PARAM1:%[^\)]+]]) +// CHECK: [[ALIGNCAST1:%.+]] = sext i32 [[PARAM1]] to i64 +// CHECK: [[ISPOS1:%.+]] = icmp sgt i64 [[ALIGNCAST1]], 0 +// CHECK: [[POSMASK1:%.+]] = sub i64 [[ALIGNCAST1]], 1 +// CHECK: [[MASK1:%.+]] = select i1 [[ISPOS1]], i64 [[POSMASK1]], i64 0 +// CHECK: [[PTRINT1:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR1:%.+]] = and i64 [[PTRINT1]], [[MASK1]] +// CHECK: [[MASKCOND1:%.+]] = icmp eq i64 [[MASKEDPTR1]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND1]]) +} +// Condition where test2 param needs casting. +__INT32_TYPE__ test2(__SIZE_TYPE__ a) { +// CHECK: define i32 @test2 + return *m1(a); +// CHECK: [[CONV2:%.+]] = trunc i64 %{{.+}} to i32 +// CHECK: call i32* @m1(i32 [[CONV2]]) +// CHECK: [[ALIGNCAST2:%.+]] = sext i32 [[CONV2]] to i64 +// CHECK: [[ISPOS2:%.+]] = icmp sgt i64 [[ALIGNCAST2]], 0 +// CHECK: [[POSMASK2:%.+]] = sub i64 [[ALIGNCAST2]], 1 +// CHECK: [[MASK2:%.+]] = select i1 [[ISPOS2]], i64 [[POSMASK2]], i64 0 +// CHECK: [[PTRINT2:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR2:%.+]] = and i64 [[PTRINT2]], [[MASK2]] +// CHECK: [[MASKCOND2:%.+]] = icmp eq i64 [[MASKEDPTR2]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND2]]) +} +__INT32_TYPE__ *m2(__SIZE_TYPE__ i) __attribute__((alloc_align(1))); + +// test3 param needs casting, but 'm2' is correct. +__INT32_TYPE__ test3(__INT32_TYPE__ a) { +// CHECK: define i32 @test3 + return *m2(a); +// CHECK: [[CONV3:%.+]] = sext i32 %{{.+}} to i64 +// CHECK: call i32* @m2(i64 [[CONV3]]) +// CHECK: [[ISPOS3:%.+]] = icmp sgt i64 [[CONV3]], 0 +// CHECK: [[POSMASK3:%.+]] = sub i64 [[CONV3]], 1 +// CHECK: [[MASK3:%.+]] = select i1 [[ISPOS3]], i64 [[POSMASK3]], i64 0 +// CHECK: [[PTRINT3:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR3:%.+]] = and i64 [[PTRINT3]], [[MASK3]] +// CHECK: [[MASKCOND3:%.+]] = icmp eq i64 [[MASKEDPTR3]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND3]]) +} + +// Every type matches, canonical example. +__INT32_TYPE__ test4(__SIZE_TYPE__ a) { +// CHECK: define i32 @test4 + return *m2(a); +// CHECK: call i32* @m2(i64 [[PARAM4:%[^\)]+]]) +// CHECK: [[ISPOS4:%.+]] = icmp sgt i64 [[PARAM4]], 0 +// CHECK: [[POSMASK4:%.+]] = sub i64 [[PARAM4]], 1 +// CHECK: [[MASK4:%.+]] = select i1 [[ISPOS4]], i64 [[POSMASK4]], i64 0 +// CHECK: [[PTRINT4:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR4:%.+]] = and i64 [[PTRINT4]], [[MASK4]] +// CHECK: [[MASKCOND4:%.+]] = icmp eq i64 [[MASKEDPTR4]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND4]]) +} + + +struct Empty {}; +struct MultiArgs { __INT64_TYPE__ a, b;}; +// Struct parameter doesn't take up an IR parameter, 'i' takes up 2. +// Truncation to i64 is permissible, since alignments of greater than 2^64 are insane. +__INT32_TYPE__ *m3(struct Empty s, __int128_t i) __attribute__((alloc_align(2))); +__INT32_TYPE__ test5(__int128_t a) { +// CHECK: define i32 @test5 + struct Empty e; + return *m3(e, a); +// CHECK: call i32* @m3(i64 %{{.*}}, i64 %{{.*}}) +// CHECK: [[ALIGNCAST5:%.+]] = trunc i128 %{{.*}} to i64 +// CHECK: [[ISPOS5:%.+]] = icmp sgt i64 [[ALIGNCAST5]], 0 +// CHECK: [[POSMASK5:%.+]] = sub i64 [[ALIGNCAST5]], 1 +// CHECK: [[MASK5:%.+]] = select i1 [[ISPOS5]], i64 [[POSMASK5]], i64 0 +// CHECK: [[PTRINT5:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR5:%.+]] = and i64 [[PTRINT5]], [[MASK5]] +// CHECK: [[MASKCOND5:%.+]] = icmp eq i64 [[MASKEDPTR5]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND5]]) +} +// Struct parameter takes up 2 parameters, 'i' takes up 2. +__INT32_TYPE__ *m4(struct MultiArgs s, __int128_t i) __attribute__((alloc_align(2))); +__INT32_TYPE__ test6(__int128_t a) { +// CHECK: define i32 @test6 + struct MultiArgs e; + return *m4(e, a); +// CHECK: call i32* @m4(i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}) +// CHECK: [[ALIGNCAST6:%.+]] = trunc i128 %{{.*}} to i64 +// CHECK: [[ISPOS6:%.+]] = icmp sgt i64 [[ALIGNCAST6]], 0 +// CHECK: [[POSMASK6:%.+]] = sub i64 [[ALIGNCAST6]], 1 +// CHECK: [[MASK6:%.+]] = select i1 [[ISPOS6]], i64 [[POSMASK6]], i64 0 +// CHECK: [[PTRINT6:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR6:%.+]] = and i64 [[PTRINT6]], [[MASK6]] +// CHECK: [[MASKCOND6:%.+]] = icmp eq i64 [[MASKEDPTR6]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND6]]) +} + diff --git a/clang/test/Sema/alloc-align-attr.c b/clang/test/Sema/alloc-align-attr.c new file mode 100644 index 00000000000..bf8591625da --- /dev/null +++ b/clang/test/Sema/alloc-align-attr.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// return values +void test_void_alloc_align(void) __attribute__((alloc_align(1))); // expected-warning {{'alloc_align' attribute only applies to return values that are pointers}} +void *test_ptr_alloc_align(int a) __attribute__((alloc_align(1))); // no-warning + +int j __attribute__((alloc_align(1))); // expected-warning {{'alloc_align' attribute only applies to non-K&R-style functions}} +void *test_no_params_zero(void) __attribute__((alloc_align(0))); // expected-error {{'alloc_align' attribute parameter 1 is out of bounds}} +void *test_no_params(void) __attribute__((alloc_align(1))); // expected-error {{'alloc_align' attribute parameter 1 is out of bounds}} +void *test_incorrect_param_type(float a) __attribute__((alloc_align(1))); // expected-error {{'alloc_align' attribute argument may only refer to a function parameter of integer type}} + +// argument type +void *test_bad_param_type(void) __attribute((alloc_align(1.1))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}} + +// argument count +void *test_no_fn_proto() __attribute__((alloc_align)); // expected-error {{'alloc_align' attribute takes one argument}} +void *test_no_fn_proto() __attribute__((alloc_align())); // expected-error {{'alloc_align' attribute takes one argument}} +void *test_no_fn_proto() __attribute__((alloc_align(32, 45, 37))); // expected-error {{'alloc_align' attribute takes one argument}} + diff --git a/clang/test/SemaCXX/alloc-align-attr.cpp b/clang/test/SemaCXX/alloc-align-attr.cpp new file mode 100644 index 00000000000..74cfb7d7e48 --- /dev/null +++ b/clang/test/SemaCXX/alloc-align-attr.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct param_num { + void* Foo(int a) __attribute__((alloc_align(1))); // expected-error {{'alloc_align' attribute is invalid for the implicit this argument}} +}; + + +template <typename T> +struct dependent_ret { + T* Foo(int a) __attribute__((alloc_align(2)));// no-warning, ends up being int**. + T Foo2(int a) __attribute__((alloc_align(2)));// expected-warning {{'alloc_align' attribute only applies to return values that are pointers or references}} +}; + +// Following 2 errors associated only with the 'float' versions below. +template <typename T> +struct dependent_param_struct { + void* Foo(T param) __attribute__((alloc_align(2))); // expected-error {{'alloc_align' attribute argument may only refer to a function parameter of integer type}} +}; + +template <typename T> +void* dependent_param_func(T param) __attribute__((alloc_align(1)));// expected-error {{'alloc_align' attribute argument may only refer to a function parameter of integer type}} + +template <int T> +void* illegal_align_param(int p) __attribute__((alloc_align(T))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}} + +void dependent_impl() { + dependent_ret<int> a; // expected-note {{in instantiation of template class 'dependent_ret<int>' requested here}} + a.Foo(1); + a.Foo2(1); + dependent_ret<int*> b; + a.Foo(1); + a.Foo2(1); + + dependent_param_struct<int> c; + c.Foo(1); + dependent_param_struct<float> d; // expected-note {{in instantiation of template class 'dependent_param_struct<float>' requested here}} + d.Foo(1.0); + dependent_param_func<int>(1); + dependent_param_func<float>(1); // expected-note {{in instantiation of function template specialization 'dependent_param_func<float>' requested here}} +} |