member-function-pointers.cpp revision e174bd05ca9991e705f51afcfab27933b537dc63
1// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s
2// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-apple-darwin9 | FileCheck -check-prefix LP32 %s
3
4struct A { int a; void f(); virtual void vf1(); virtual void vf2(); };
5struct B { int b; virtual void g(); };
6struct C : B, A { };
7
8void (A::*pa)();
9void (A::*volatile vpa)();
10void (B::*pb)();
11void (C::*pc)();
12
13// CHECK: @pa2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }, align 8
14void (A::*pa2)() = &A::f;
15
16// CHECK:      @pa3 = global %0 { i64 1, i64 0 }, align 8
17// CHECK-LP32: @pa3 = global %0 { i32 1, i32 0 }, align 4
18void (A::*pa3)() = &A::vf1;
19
20// CHECK:      @pa4 = global %0 { i64 9, i64 0 }, align 8
21// CHECK-LP32: @pa4 = global %0 { i32 5, i32 0 }, align 4
22void (A::*pa4)() = &A::vf2;
23
24// CHECK: @pc2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 16 }, align 8
25void (C::*pc2)() = &C::f;
26
27// CHECK: @pc3 = global %0 { i64 1, i64 0 }, align 8
28void (A::*pc3)() = &A::vf1;
29
30void f() {
31  // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
32  // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
33  pa = 0;
34
35  // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 0)
36  // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 1)
37  vpa = 0;
38
39  // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pc, i32 0, i32 0)
40  // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 16
41  // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pc, i32 0, i32 1)
42  pc = pa;
43
44  // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
45  // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 16
46  // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
47  pa = static_cast<void (A::*)()>(pc);
48}
49
50void f2() {
51  // CHECK: [[pa2ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 0
52  // CHECK: store i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64* [[pa2ptr]]
53  // CHECK: [[pa2adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 1
54  // CHECK: store i64 0, i64* [[pa2adj]]
55  void (A::*pa2)() = &A::f;
56
57  // CHECK:      [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0
58  // CHECK:      store i64 1, i64* [[pa3ptr]]
59  // CHECK:      [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
60  // CHECK:      store i64 0, i64* [[pa3adj]]
61  // CHECK-LP32: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0
62  // CHECK-LP32: store i32 1, i32* [[pa3ptr]]
63  // CHECK-LP32: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
64  // CHECK-LP32: store i32 0, i32* [[pa3adj]]
65  void (A::*pa3)() = &A::vf1;
66
67  // CHECK:      [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0
68  // CHECK:      store i64 9, i64* [[pa4ptr]]
69  // CHECK:      [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
70  // CHECK:      store i64 0, i64* [[pa4adj]]
71  // CHECK-LP32: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0
72  // CHECK-LP32: store i32 5, i32* [[pa4ptr]]
73  // CHECK-LP32: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
74  // CHECK-LP32: store i32 0, i32* [[pa4adj]]
75  void (A::*pa4)() = &A::vf2;
76}
77
78void f3(A *a, A &ar) {
79  (a->*pa)();
80  (ar.*pa)();
81}
82
83bool f4() {
84  return pa;
85}
86
87// PR5177
88namespace PR5177 {
89  struct A {
90   bool foo(int*) const;
91  } a;
92
93  struct B1 {
94   bool (A::*pmf)(int*) const;
95   const A* pa;
96
97   B1() : pmf(&A::foo), pa(&a) {}
98   bool operator()() const { return (pa->*pmf)(new int); }
99  };
100
101  void bar(B1 b2) { while (b2()) ; }
102}
103
104// PR5138
105namespace PR5138 {
106  struct foo {
107      virtual void bar(foo *);
108  };
109
110  extern "C" {
111    void baz(foo *);
112  }
113
114  void (foo::*ptr1)(void *) = (void (foo::*)(void *))&foo::bar;
115  void (*ptr2)(void *) = (void (*)(void *))&baz;
116
117  void (foo::*ptr3)(void) = (void (foo::*)(void))&foo::bar;
118}
119
120// PR5593
121namespace PR5593 {
122  struct A { };
123
124  bool f(void (A::*f)()) {
125    return f && f;
126  }
127}
128
129namespace PR5718 {
130  struct A { };
131
132  bool f(void (A::*f)(), void (A::*g)()) {
133    return f == g;
134  }
135}
136
137namespace BoolMemberPointer {
138  struct A { };
139
140  bool f(void (A::*f)()) {
141    return !f;
142  }
143
144  bool g(void (A::*f)()) {
145    if (!!f)
146      return true;
147    return false;
148  }
149}
150
151// PR5940
152namespace PR5940 {
153  class foo {
154  public:
155    virtual void baz(void);
156  };
157
158  void foo::baz(void) {
159       void (foo::*ptr)(void) = &foo::baz;
160  }
161}
162
163namespace MemberPointerImpCast {
164  struct A {
165    int x;
166  };
167  struct B : public A {
168  };
169  void f(B* obj, void (A::*method)()) {
170    (obj->*method)();
171  }
172}
173
174// PR6258
175namespace PR6258 {
176
177  struct A {
178    void f(bool);
179  };
180
181  void (A::*pf)(bool) = &A::f;
182
183  void f() {
184    void (A::*pf)(bool) = &A::f;
185  }
186}
187
188// PR7027
189namespace PR7027 {
190  struct X { void test( ); };
191  void testX() { &X::test; }
192}
193