1ac991bbbSJohannes Doerfert // RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
2ac991bbbSJohannes Doerfert
3ac991bbbSJohannes Doerfert struct Base {
4ac991bbbSJohannes Doerfert
5ac991bbbSJohannes Doerfert void no_args_1(void (*callback)(void));
6ac991bbbSJohannes Doerfert __attribute__((callback(1))) void no_args_2(void (*callback1)(void), void (*callback2)(void));
7ac991bbbSJohannes Doerfert __attribute__((callback(callback1))) void no_args_3(void (*callback1)(void), void (*callback2)(void));
8ac991bbbSJohannes Doerfert
9ac991bbbSJohannes Doerfert // TODO: There should probably be a warning or even an error for different
10ac991bbbSJohannes Doerfert // callbacks on the same method.
11ac991bbbSJohannes Doerfert __attribute__((callback(1))) virtual void
12ac991bbbSJohannes Doerfert virtual_1(void (*callback)(void));
13ac991bbbSJohannes Doerfert
14ac991bbbSJohannes Doerfert __attribute__((callback(callback, this, __, this))) virtual void
15ac991bbbSJohannes Doerfert this_unknown_this(void (*callback)(Base *, Base *, Base *));
16ac991bbbSJohannes Doerfert };
17ac991bbbSJohannes Doerfert
18*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN4Base9no_args_1EPFvvE({{[^!]*!callback}} ![[cid0:[0-9]+]]
19ac991bbbSJohannes Doerfert __attribute__((callback(1))) void
no_args_1(void (* callback)(void))20ac991bbbSJohannes Doerfert Base::no_args_1(void (*callback)(void)) {
21ac991bbbSJohannes Doerfert }
22ac991bbbSJohannes Doerfert
23*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN4Base9no_args_2EPFvvES1_({{[^!]*!callback}} ![[cid1:[0-9]+]]
no_args_2(void (* callback1)(void),void (* callback2)(void))24ac991bbbSJohannes Doerfert __attribute__((callback(2))) void Base::no_args_2(void (*callback1)(void), void (*callback2)(void)) {
25ac991bbbSJohannes Doerfert }
26*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN4Base9no_args_3EPFvvES1_({{[^!]*!callback}} ![[cid1]]
no_args_3(void (* callback1)(void),void (* callback2)(void))27ac991bbbSJohannes Doerfert __attribute__((callback(callback2))) void Base::no_args_3(void (*callback1)(void), void (*callback2)(void)) {
28ac991bbbSJohannes Doerfert }
29ac991bbbSJohannes Doerfert
30*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN4Base17this_unknown_thisEPFvPS_S0_S0_E({{[^!]*!callback}} ![[cid2:[0-9]+]]
this_unknown_this(void (* callback)(Base *,Base *,Base *))31ac991bbbSJohannes Doerfert void Base::this_unknown_this(void (*callback)(Base *, Base *, Base *)) {
32ac991bbbSJohannes Doerfert }
33ac991bbbSJohannes Doerfert
34ac991bbbSJohannes Doerfert struct Derived_1 : public Base {
35ac991bbbSJohannes Doerfert __attribute__((callback(1))) virtual void
36ac991bbbSJohannes Doerfert virtual_1(void (*callback)(void)) override;
37ac991bbbSJohannes Doerfert };
38ac991bbbSJohannes Doerfert
39*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN9Derived_19virtual_1EPFvvE({{[^!]*!callback}} ![[cid0]]
virtual_1(void (* callback)(void))40ac991bbbSJohannes Doerfert void Derived_1::virtual_1(void (*callback)(void)) {}
41ac991bbbSJohannes Doerfert
42ac991bbbSJohannes Doerfert struct Derived_2 : public Base {
43ac991bbbSJohannes Doerfert void virtual_1(void (*callback)(void)) override;
44ac991bbbSJohannes Doerfert };
45ac991bbbSJohannes Doerfert
46*fd739804SFangrui Song // CHECK-DAG: define{{.*}} void @_ZN9Derived_29virtual_1EPFvvE
47ac991bbbSJohannes Doerfert // CHECK-NOT: !callback
virtual_1(void (* callback)(void))48ac991bbbSJohannes Doerfert void Derived_2::virtual_1(void (*callback)(void)) {}
49ac991bbbSJohannes Doerfert
50ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid0]] = !{![[cid0b:[0-9]+]]}
51ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid0b]] = !{i64 1, i1 false}
52ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid1]] = !{![[cid1b:[0-9]+]]}
53ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid1b]] = !{i64 2, i1 false}
54ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid2]] = !{![[cid2b:[0-9]+]]}
55ac991bbbSJohannes Doerfert // CHECK-DAG: ![[cid2b]] = !{i64 1, i64 0, i64 -1, i64 0, i1 false}
56