diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/Analysis/retain-release.m | 4 | ||||
-rw-r--r-- | clang/test/CodeGen/attr-callback.c | 28 | ||||
-rw-r--r-- | clang/test/CodeGen/callback_annotated.c | 73 | ||||
-rw-r--r-- | clang/test/CodeGen/callback_openmp.c | 28 | ||||
-rw-r--r-- | clang/test/CodeGen/callback_pthread_create.c | 32 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/attr-callback.cpp | 55 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 | ||||
-rw-r--r-- | clang/test/OpenMP/parallel_codegen.cpp | 7 | ||||
-rw-r--r-- | clang/test/Sema/attr-callback-broken.c | 75 | ||||
-rw-r--r-- | clang/test/Sema/attr-callback.c | 14 | ||||
-rw-r--r-- | clang/test/SemaCXX/attr-callback-broken.cpp | 7 | ||||
-rw-r--r-- | clang/test/SemaCXX/attr-callback.cpp | 67 |
12 files changed, 386 insertions, 5 deletions
diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index 5e858f9f543..81acf0a9625 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -2,7 +2,7 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ // RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ // RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\ -// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\ +// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify=expected,C %s\ // RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objc.plist // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ // RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ @@ -1202,7 +1202,7 @@ typedef __darwin_pthread_attr_t pthread_attr_t; typedef unsigned long __darwin_pthread_key_t; typedef __darwin_pthread_key_t pthread_key_t; -int pthread_create(pthread_t *, const pthread_attr_t *, +int pthread_create(pthread_t *, const pthread_attr_t *, // C-warning{{declaration of built-in function 'pthread_create' requires inclusion of the header <pthread.h>}} void *(*)(void *), void *); int pthread_setspecific(pthread_key_t key, const void *value); diff --git a/clang/test/CodeGen/attr-callback.c b/clang/test/CodeGen/attr-callback.c new file mode 100644 index 00000000000..5d96b835285 --- /dev/null +++ b/clang/test/CodeGen/attr-callback.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s + +void cb0(void); + +// CHECK-DAG: !callback ![[cid0:[0-9]+]] void @no_args +__attribute__((callback(1))) void no_args(void (*callback)(void)); + +// CHECK-DAG: @args_1({{[^#]*#[0-9]+}} !callback ![[cid1:[0-9]+]] +__attribute__((callback(1, 2, 3))) void args_1(void (*callback)(int, double), int a, double b) { no_args(cb0); } + +// CHECK-DAG: !callback ![[cid2:[0-9]+]] void @args_2a +__attribute__((callback(2, 3, 3))) void args_2a(int a, void (*callback)(double, double), double b); +// CHECK-DAG: !callback ![[cid2]] void @args_2b +__attribute__((callback(callback, b, b))) void args_2b(int a, void (*callback)(double, double), double b); + +// CHECK-DAG: void @args_3a({{[^#]*#[0-9]+}} !callback ![[cid3:[0-9]+]] +__attribute__((callback(2, -1, -1))) void args_3a(int a, void (*callback)(double, double), double b) { args_2a(a, callback, b); } +// CHECK-DAG: void @args_3b({{[^#]*#[0-9]+}} !callback ![[cid3]] +__attribute__((callback(callback, __, __))) void args_3b(int a, void (*callback)(double, double), double b) { args_2b(a, callback, b); } + +// CHECK-DAG: ![[cid0]] = !{![[cid0b:[0-9]+]]} +// CHECK-DAG: ![[cid0b]] = !{i64 0, i1 false} +// CHECK-DAG: ![[cid1]] = !{![[cid1b:[0-9]+]]} +// CHECK-DAG: ![[cid1b]] = !{i64 0, i64 1, i64 2, i1 false} +// CHECK-DAG: ![[cid2]] = !{![[cid2b:[0-9]+]]} +// CHECK-DAG: ![[cid2b]] = !{i64 1, i64 2, i64 2, i1 false} +// CHECK-DAG: ![[cid3]] = !{![[cid3b:[0-9]+]]} +// CHECK-DAG: ![[cid3b]] = !{i64 1, i64 -1, i64 -1, i1 false} diff --git a/clang/test/CodeGen/callback_annotated.c b/clang/test/CodeGen/callback_annotated.c new file mode 100644 index 00000000000..5a4314c60ba --- /dev/null +++ b/clang/test/CodeGen/callback_annotated.c @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fopenmp -O1 %s -emit-llvm -o - | FileCheck %s --check-prefix=RUN1 +// RUN: %clang_cc1 -triple i386-unknown-unknown -fopenmp -O1 %s -emit-llvm -o - | FileCheck %s --check-prefix=RUN2 +// RUN: %clang_cc1 -triple i386-unknown-unknown -fopenmp -O1 %s -emit-llvm -o - | opt -ipconstprop -S | FileCheck --check-prefix=IPCP %s + +// RUN1-DAG: @broker0({{[^#]*#[0-9]+}} !callback ![[cid0:[0-9]+]] +__attribute__((callback(1, 2))) void *broker0(void *(*callee)(void *), void *payload) { + return callee(payload); +} + +// RUN1-DAG: @broker1({{[^#]*#[0-9]+}} !callback ![[cid1:[0-9]+]] +__attribute__((callback(callee, payload))) void *broker1(void *payload, void *(*callee)(void *)) { + return broker0(callee, payload); +} + +void *broker2(void (*callee)(void)); + +// RUN1-DAG: declare !callback ![[cid2:[0-9]+]] i8* @broker2 +__attribute__((callback(callee))) void *broker2(void (*callee)(void)); + +void *broker2(void (*callee)(void)); + +// RUN1-DAG: declare !callback ![[cid3:[0-9]+]] i8* @broker3 +__attribute__((callback(4, 1, 2, c))) void *broker3(int, int, int c, int (*callee)(int, int, int), int); + +// RUN1-DAG: declare !callback ![[cid4:[0-9]+]] i8* @broker4 +__attribute__((callback(4, -1, a, __))) void *broker4(int a, int, int, int (*callee)(int, int, int), int); + +// RUN1-DAG: declare !callback ![[cid5:[0-9]+]] i8* @broker5 +__attribute__((callback(4, d, 5, 2))) void *broker5(int, int, int, int (*callee)(int, int, int), int d); + +static void *VoidPtr2VoidPtr(void *payload) { + // RUN2: ret i8* %payload + // IPCP: ret i8* null + return payload; +} + +static int ThreeInt2Int(int a, int b, int c) { + // RUN2: define internal i32 @ThreeInt2Int(i32 %a, i32 %b, i32 %c) + // RUN2-NEXT: entry: + // RUN2-NEXT: %mul = mul nsw i32 %b, %a + // RUN2-NEXT: %add = add nsw i32 %mul, %c + // RUN2-NEXT: ret i32 %add + + // IPCP: define internal i32 @ThreeInt2Int(i32 %a, i32 %b, i32 %c) + // IPCP-NEXT: entry: + // IPCP-NEXT: %mul = mul nsw i32 4, %a + // IPCP-NEXT: %add = add nsw i32 %mul, %c + // IPCP-NEXT: ret i32 %add + + return a * b + c; +} + +void foo() { + broker0(VoidPtr2VoidPtr, 0l); + broker1(0l, VoidPtr2VoidPtr); + broker2(foo); + broker3(1, 4, 5, ThreeInt2Int, 1); + broker4(4, 2, 7, ThreeInt2Int, 0); + broker5(8, 0, 3, ThreeInt2Int, 4); +} + +// RUN1-DAG: ![[cid0]] = !{![[cid0b:[0-9]+]]} +// RUN1-DAG: ![[cid0b]] = !{i64 0, i64 1, i1 false} +// RUN1-DAG: ![[cid1]] = !{![[cid1b:[0-9]+]]} +// RUN1-DAG: ![[cid1b]] = !{i64 1, i64 0, i1 false} +// RUN1-DAG: ![[cid2]] = !{![[cid2b:[0-9]+]]} +// RUN1-DAG: ![[cid2b]] = !{i64 0, i1 false} +// RUN1-DAG: ![[cid3]] = !{![[cid3b:[0-9]+]]} +// RUN1-DAG: ![[cid3b]] = !{i64 3, i64 0, i64 1, i64 2, i1 false} +// RUN1-DAG: ![[cid4]] = !{![[cid4b:[0-9]+]]} +// RUN1-DAG: ![[cid4b]] = !{i64 3, i64 -1, i64 0, i64 -1, i1 false} +// RUN1-DAG: ![[cid5]] = !{![[cid5b:[0-9]+]]} +// RUN1-DAG: ![[cid5b]] = !{i64 3, i64 4, i64 4, i64 1, i1 false} diff --git a/clang/test/CodeGen/callback_openmp.c b/clang/test/CodeGen/callback_openmp.c new file mode 100644 index 00000000000..2fc9dcd391f --- /dev/null +++ b/clang/test/CodeGen/callback_openmp.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fopenmp -O1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -fopenmp -O1 %s -emit-llvm -o - | opt -ipconstprop -S | FileCheck --check-prefix=IPCP %s + +// CHECK: declare !callback ![[cid:[0-9]+]] void @__kmpc_fork_call +// CHECK: declare !callback ![[cid]] void @__kmpc_fork_teams +// CHECK: ![[cid]] = !{![[cidb:[0-9]+]]} +// CHECK: ![[cidb]] = !{i64 2, i64 -1, i64 -1, i1 true} + +void work1(int, int); +void work2(int, int); +void work12(int, int); + +void foo(int q) { + int p = 2; + + #pragma omp parallel firstprivate(q, p) + work1(p, q); +// IPCP: call void @work1(i32 2, i32 %{{[._a-zA-Z0-9]*}}) + + #pragma omp parallel for firstprivate(p, q) + for (int i = 0; i < q; i++) + work2(i, p); +// IPCP: call void @work2(i32 %{{[._a-zA-Z0-9]*}}, i32 2) + + #pragma omp target teams firstprivate(p) + work12(p, p); +// IPCP: call void @work12(i32 2, i32 2) +} diff --git a/clang/test/CodeGen/callback_pthread_create.c b/clang/test/CodeGen/callback_pthread_create.c new file mode 100644 index 00000000000..d751e8abb3f --- /dev/null +++ b/clang/test/CodeGen/callback_pthread_create.c @@ -0,0 +1,32 @@ +// RUN: %clang -O1 %s -S -c -emit-llvm -o - | FileCheck %s +// RUN: %clang -O1 %s -S -c -emit-llvm -o - | opt -ipconstprop -S | FileCheck --check-prefix=IPCP %s + +// CHECK: declare !callback ![[cid:[0-9]+]] dso_local i32 @pthread_create +// CHECK: ![[cid]] = !{![[cidb:[0-9]+]]} +// CHECK: ![[cidb]] = !{i64 2, i64 3, i1 false} + +#include <pthread.h> + +const int GlobalVar = 0; + +static void *callee0(void *payload) { +// IPCP: define internal i8* @callee0 +// IPCP-NEXT: entry: +// IPCP-NEXT: ret i8* null + return payload; +} + +static void *callee1(void *payload) { +// IPCP: define internal i8* @callee1 +// IPCP-NEXT: entry: +// IPCP-NEXT: ret i8* bitcast (i32* @GlobalVar to i8*) + return payload; +} + +void foo() { + pthread_t MyFirstThread; + pthread_create(&MyFirstThread, NULL, callee0, NULL); + + pthread_t MySecondThread; + pthread_create(&MySecondThread, NULL, callee1, (void *)&GlobalVar); +} diff --git a/clang/test/CodeGenCXX/attr-callback.cpp b/clang/test/CodeGenCXX/attr-callback.cpp new file mode 100644 index 00000000000..a05b640b601 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-callback.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s + +struct Base { + + void no_args_1(void (*callback)(void)); + __attribute__((callback(1))) void no_args_2(void (*callback1)(void), void (*callback2)(void)); + __attribute__((callback(callback1))) void no_args_3(void (*callback1)(void), void (*callback2)(void)); + + // TODO: There should probably be a warning or even an error for different + // callbacks on the same method. + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)); + + __attribute__((callback(callback, this, __, this))) virtual void + this_unknown_this(void (*callback)(Base *, Base *, Base *)); +}; + +// CHECK-DAG: define void @_ZN4Base9no_args_1EPFvvE({{[^!]*!callback}} ![[cid0:[0-9]+]] +__attribute__((callback(1))) void +Base::no_args_1(void (*callback)(void)) { +} + +// CHECK-DAG: define void @_ZN4Base9no_args_2EPFvvES1_({{[^!]*!callback}} ![[cid1:[0-9]+]] +__attribute__((callback(2))) void Base::no_args_2(void (*callback1)(void), void (*callback2)(void)) { +} +// CHECK-DAG: define void @_ZN4Base9no_args_3EPFvvES1_({{[^!]*!callback}} ![[cid1]] +__attribute__((callback(callback2))) void Base::no_args_3(void (*callback1)(void), void (*callback2)(void)) { +} + +// CHECK-DAG: define void @_ZN4Base17this_unknown_thisEPFvPS_S0_S0_E({{[^!]*!callback}} ![[cid2:[0-9]+]] +void Base::this_unknown_this(void (*callback)(Base *, Base *, Base *)) { +} + +struct Derived_1 : public Base { + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)) override; +}; + +// CHECK-DAG: define void @_ZN9Derived_19virtual_1EPFvvE({{[^!]*!callback}} ![[cid0]] +void Derived_1::virtual_1(void (*callback)(void)) {} + +struct Derived_2 : public Base { + void virtual_1(void (*callback)(void)) override; +}; + +// CHECK-DAG: define void @_ZN9Derived_29virtual_1EPFvvE +// CHECK-NOT: !callback +void Derived_2::virtual_1(void (*callback)(void)) {} + +// CHECK-DAG: ![[cid0]] = !{![[cid0b:[0-9]+]]} +// CHECK-DAG: ![[cid0b]] = !{i64 1, i1 false} +// CHECK-DAG: ![[cid1]] = !{![[cid1b:[0-9]+]]} +// CHECK-DAG: ![[cid1b]] = !{i64 2, i1 false} +// CHECK-DAG: ![[cid2]] = !{![[cid2b:[0-9]+]]} +// CHECK-DAG: ![[cid2b]] = !{i64 1, i64 0, i64 -1, i64 0, i1 false} diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 9dec259f4fc..e0c074556c4 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -32,6 +32,7 @@ // CHECK-NEXT: CUDAShared (SubjectMatchRule_variable) // CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function) // CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member) +// CHECK-NEXT: Callback (SubjectMatchRule_function) // CHECK-NEXT: Capability (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: Cold (SubjectMatchRule_function) diff --git a/clang/test/OpenMP/parallel_codegen.cpp b/clang/test/OpenMP/parallel_codegen.cpp index 19eebc8289a..ae117a0aad7 100644 --- a/clang/test/OpenMP/parallel_codegen.cpp +++ b/clang/test/OpenMP/parallel_codegen.cpp @@ -82,9 +82,9 @@ int main (int argc, char **argv) { // CHECK-DEBUG-NEXT: } // CHECK-DAG: define linkonce_odr {{.*}}void [[FOO]]({{i32[ ]?[a-z]*}} %argc) -// CHECK-DAG: declare {{.*}}void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +// CHECK-DAG: declare !callback ![[cbid:[0-9]+]] {{.*}}void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) // CHECK-DEBUG-DAG: define linkonce_odr void [[FOO]](i32 %argc) -// CHECK-DEBUG-DAG: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +// CHECK-DEBUG-DAG: declare !callback ![[cbid:[0-9]+]] void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) // CHECK-DEBUG-DAG: define internal void [[OMP_OUTLINED]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* {{.+}} [[VLA_ADDR:%[^)]+]]) // CHECK-DEBUG-DAG: call void [[OMP_OUTLINED_DEBUG]] @@ -131,5 +131,6 @@ int main (int argc, char **argv) { // CHECK: attributes #[[FN_ATTRS]] = {{.+}} nounwind // CHECK-DEBUG: attributes #[[FN_ATTRS]] = {{.+}} nounwind - +// CHECK: ![[cbid]] = !{![[cbidb:[0-9]+]]} +// CHECK: ![[cbidb]] = !{i64 2, i64 -1, i64 -1, i1 true} #endif diff --git a/clang/test/Sema/attr-callback-broken.c b/clang/test/Sema/attr-callback-broken.c new file mode 100644 index 00000000000..b9e5f45f405 --- /dev/null +++ b/clang/test/Sema/attr-callback-broken.c @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +__attribute__((callback())) void no_callee(void (*callback)(void)); // expected-error {{'callback' attribute specifies no callback callee}} + +__attribute__((callback(1, 1))) void too_many_args_1(void (*callback)(void)) {} // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(1, -1))) void too_many_args_2(double (*callback)(void)); // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(1, 2, 2))) void too_many_args_3(void (*callback)(int), int); // expected-error {{'callback' attribute requires exactly 2 arguments}} + +__attribute__((callback(1, 2))) void too_few_args_1(void (*callback)(int, int), int); // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(1))) void too_few_args_2(int (*callback)(int)); // expected-error {{'callback' attribute takes no arguments}} +__attribute__((callback(1, -1))) void too_few_args_3(void (*callback)(int, int)) {} // expected-error {{'callback' attribute takes one argument}} + +__attribute__((callback(-1))) void oob_args_1(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}} +__attribute__((callback(2))) void oob_args_2(int *(*callback)(void)) {} // expected-error {{'callback' attribute parameter 1 is out of bounds}} +__attribute__((callback(1, 3))) void oob_args_3(short (*callback)(int), int); // expected-error {{'callback' attribute parameter 2 is out of bounds}} +__attribute__((callback(-2, 2))) void oob_args_4(void *(*callback)(int), int); // expected-error {{'callback' attribute parameter 1 is out of bounds}} +__attribute__((callback(1, -2))) void oob_args_5(void *(*callback)(int), int); // expected-error {{'callback' attribute parameter 2 is out of bounds}} +__attribute__((callback(1, 2))) void oob_args_6(void *(*callback)(int), ...); // expected-error {{'callback' attribute parameter 2 is out of bounds}} + +__attribute__((callback(1))) __attribute__((callback(1))) void multiple_cb_1(void (*callback)(void)); // expected-error {{multiple 'callback' attributes specified}} +__attribute__((callback(1))) __attribute__((callback(2))) void multiple_cb_2(void (*callback1)(void), void (*callback2)(void)); // expected-error {{multiple 'callback' attributes specified}} + +#ifdef HAS_THIS +__attribute__((callback(0))) void oob_args_0(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}} +#else +__attribute__((callback(0))) void oob_args_0(void (*callback)(void)); // expected-error {{'callback' argument at position 1 references unavailable implicit 'this'}} +__attribute__((callback(1, 0))) void no_this_1(void *(*callback)(void *)); // expected-error {{'callback' argument at position 2 references unavailable implicit 'this'}} +__attribute__((callback(1, 0))) void no_this_2(void *(*callback)(int, void *)); // expected-error {{'callback' argument at position 2 references unavailable implicit 'this'}} +#endif + +// We could allow the following declarations if we at some point need to: + +__attribute__((callback(1, -1))) void vararg_cb_1(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute callee may not be variadic}} +__attribute__((callback(1, 1))) void vararg_cb_2(void (*callback)(int, ...), int a); // expected-error {{'callback' attribute callee may not be variadic}} + +__attribute__((callback(1, -1, 1, 2, 3, 4, -1))) void varargs_1(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute requires exactly 6 arguments}} +__attribute__((callback(1, -1, 4, 2, 3, 4, -1))) void varargs_2(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute requires exactly 6 arguments}} + +__attribute__((callback(1, -1, 1))) void self_arg_1(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute requires exactly 2 arguments}} +__attribute__((callback(1, -1, 1, -1, -1, 1))) void self_arg_2(void (*callback)(int, ...)); // expected-error {{'callback' attribute requires exactly 5 arguments}} + +__attribute__((callback(cb))) void unknown_name1(void (*callback)(void)) {} // expected-error {{'callback' attribute argument 'cb' is not a known function parameter}} +__attribute__((callback(cb, ab))) void unknown_name2(void (*cb)(int), int a) {} // expected-error {{'callback' attribute argument 'ab' is not a known function parameter}} + +__attribute__((callback(callback, 1))) void too_many_args_1b(void (*callback)(void)) {} // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(callback, __))) void too_many_args_2b(double (*callback)(void)); // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(callback, 2, 2))) void too_many_args_3b(void (*callback)(int), int); // expected-error {{'callback' attribute requires exactly 2 arguments}} + +__attribute__((callback(callback, a))) void too_few_args_1b(void (*callback)(int, int), int a); // expected-error {{'callback' attribute takes one argument}} +__attribute__((callback(callback))) void too_few_args_2b(int (*callback)(int)); // expected-error {{'callback' attribute takes no arguments}} +__attribute__((callback(callback, __))) void too_few_args_3b(void (*callback)(int, int)) {} // expected-error {{'callback' attribute takes one argument}} + +__attribute__((callback(__))) void oob_args_1b(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}} + +__attribute__((callback(callback))) __attribute__((callback(callback))) void multiple_cb_1b(void (*callback)(void)); // expected-error {{multiple 'callback' attributes specified}} +__attribute__((callback(1))) __attribute__((callback(callback2))) void multiple_cb_2b(void (*callback1)(void), void (*callback2)(void)); // expected-error {{multiple 'callback' attributes specified}} + +#ifdef HAS_THIS +__attribute__((callback(this))) void oob_args_0b(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}} +#else +__attribute__((callback(this))) void oob_args_0b(void (*callback)(void)); // expected-error {{'callback' argument at position 1 references unavailable implicit 'this'}} +__attribute__((callback(1, this))) void no_this_1b(void *(*callback)(void *)); // expected-error {{'callback' argument at position 2 references unavailable implicit 'this'}} +__attribute__((callback(1, this))) void no_this_2b(void *(*callback)(int, void *)); // expected-error {{'callback' argument at position 2 references unavailable implicit 'this'}} +#endif + +// We could allow the following declarations if we at some point need to: + +__attribute__((callback(callback, __))) void vararg_cb_1b(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute callee may not be variadic}} +__attribute__((callback(1, a))) void vararg_cb_2b(void (*callback)(int, ...), int a); // expected-error {{'callback' attribute callee may not be variadic}} + +__attribute__((callback(callback, __, callback, a, b, c, __))) void varargs_1b(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute requires exactly 6 arguments}} +__attribute__((callback(1, __, c, a, b, c, -1))) void varargs_2b(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute requires exactly 6 arguments}} + +__attribute__((callback(1, __, callback))) void self_arg_1b(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute requires exactly 2 arguments}} +__attribute__((callback(callback, __, callback, __, __, callback))) void self_arg_2b(void (*callback)(int, ...)); // expected-error {{'callback' attribute requires exactly 5 arguments}} diff --git a/clang/test/Sema/attr-callback.c b/clang/test/Sema/attr-callback.c new file mode 100644 index 00000000000..ec12b1650ac --- /dev/null +++ b/clang/test/Sema/attr-callback.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +// expected-no-diagnostics + +__attribute__((callback(1))) void no_args(void (*callback)(void)); +__attribute__((callback(1, 2, 3))) void args_1(void (*callback)(int, double), int a, double b); +__attribute__((callback(2, 3, 3))) void args_2(int a, void (*callback)(double, double), double b); +__attribute__((callback(2, -1, -1))) void args_3(int a, void (*callback)(double, double), double b); + +__attribute__((callback(callback))) void no_argsb(void (*callback)(void)); +__attribute__((callback(callback, a, 3))) void args_1b(void (*callback)(int, double), int a, double b); +__attribute__((callback(callback, b, b))) void args_2b(int a, void (*callback)(double, double), double b); +__attribute__((callback(2, __, __))) void args_3b(int a, void (*callback)(double, double), double b); +__attribute__((callback(callback, -1, __))) void args_3c(int a, void (*callback)(double, double), double b); diff --git a/clang/test/SemaCXX/attr-callback-broken.cpp b/clang/test/SemaCXX/attr-callback-broken.cpp new file mode 100644 index 00000000000..a5469b22ba3 --- /dev/null +++ b/clang/test/SemaCXX/attr-callback-broken.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +class C_in_class { +#define HAS_THIS +#include "../Sema/attr-callback-broken.c" +#undef HAS_THIS +}; diff --git a/clang/test/SemaCXX/attr-callback.cpp b/clang/test/SemaCXX/attr-callback.cpp new file mode 100644 index 00000000000..ee02f7d3d24 --- /dev/null +++ b/clang/test/SemaCXX/attr-callback.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +// expected-no-diagnostics + +class C_in_class { +#include "../Sema/attr-callback.c" +}; + +struct Base { + + void no_args_1(void (*callback)(void)); + __attribute__((callback(1))) void no_args_2(void (*callback)(void)); + __attribute__((callback(callback))) void no_args_3(void (*callback)(void)) {} + + __attribute__((callback(1, 0))) virtual void + this_tr(void (*callback)(Base *)); + + __attribute__((callback(1, this, __, this))) virtual void + this_unknown_this(void (*callback)(Base *, Base *, Base *)); + + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)); + + __attribute__((callback(callback))) virtual void + virtual_2(void (*callback)(void)); + + __attribute__((callback(1))) virtual void + virtual_3(void (*callback)(void)); +}; + +__attribute__((callback(1))) void +Base::no_args_1(void (*callback)(void)) { +} + +void Base::no_args_2(void (*callback)(void)) { +} + +struct Derived_1 : public Base { + + __attribute__((callback(1, 0))) virtual void + this_tr(void (*callback)(Base *)) override; + + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)) override {} + + virtual void + virtual_3(void (*callback)(void)) override {} +}; + +struct Derived_2 : public Base { + + __attribute__((callback(callback))) virtual void + virtual_1(void (*callback)(void)) override; + + virtual void + virtual_2(void (*callback)(void)) override; + + virtual void + virtual_3(void (*callback)(void)) override; +}; + +void Derived_2::virtual_1(void (*callback)(void)) {} + +__attribute__((callback(1))) void +Derived_2::virtual_2(void (*callback)(void)) {} + +void Derived_2::virtual_3(void (*callback)(void)) {} |