member-function-pointers.cpp revision 8bba1f4ab1f06864fec627befdf7cf8e1ad017be
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// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix ARM %s 4 5struct A { int a; void f(); virtual void vf1(); virtual void vf2(); }; 6struct B { int b; virtual void g(); }; 7struct C : B, A { }; 8 9void (A::*pa)(); 10void (A::*volatile vpa)(); 11void (B::*pb)(); 12void (C::*pc)(); 13 14// CHECK: @pa2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }, align 8 15void (A::*pa2)() = &A::f; 16 17// CHECK: @pa3 = global %0 { i64 1, i64 0 }, align 8 18// CHECK-LP32: @pa3 = global %0 { i32 1, i32 0 }, align 4 19void (A::*pa3)() = &A::vf1; 20 21// CHECK: @pa4 = global %0 { i64 9, i64 0 }, align 8 22// CHECK-LP32: @pa4 = global %0 { i32 5, i32 0 }, align 4 23void (A::*pa4)() = &A::vf2; 24 25// CHECK: @pc2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 16 }, align 8 26void (C::*pc2)() = &C::f; 27 28// CHECK: @pc3 = global %0 { i64 1, i64 0 }, align 8 29void (A::*pc3)() = &A::vf1; 30 31void f() { 32 // CHECK: store %0 zeroinitializer, %0* @pa 33 pa = 0; 34 35 // Is this okay? What are LLVM's volatile semantics for structs? 36 // CHECK: volatile store %0 zeroinitializer, %0* @vpa 37 vpa = 0; 38 39 // CHECK: [[TMP:%.*]] = load %0* @pa, align 8 40 // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1 41 // CHECK: [[ADJ:%.*]] = add nsw i64 [[TMPADJ]], 16 42 // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1 43 // CHECK: store %0 [[RES]], %0* @pc, align 8 44 pc = pa; 45 46 // CHECK: [[TMP:%.*]] = load %0* @pc, align 8 47 // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1 48 // CHECK: [[ADJ:%.*]] = sub nsw i64 [[TMPADJ]], 16 49 // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1 50 // CHECK: store %0 [[RES]], %0* @pa, align 8 51 pa = static_cast<void (A::*)()>(pc); 52} 53 54void f2() { 55 // CHECK: store %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 } 56 void (A::*pa2)() = &A::f; 57 58 // CHECK: store %0 { i64 1, i64 0 } 59 // CHECK-LP32: store %0 { i32 1, i32 0 } 60 void (A::*pa3)() = &A::vf1; 61 62 // CHECK: store %0 { i64 9, i64 0 } 63 // CHECK-LP32: store %0 { i32 5, i32 0 } 64 void (A::*pa4)() = &A::vf2; 65} 66 67void f3(A *a, A &ar) { 68 (a->*pa)(); 69 (ar.*pa)(); 70} 71 72bool f4() { 73 return pa; 74} 75 76// PR5177 77namespace PR5177 { 78 struct A { 79 bool foo(int*) const; 80 } a; 81 82 struct B1 { 83 bool (A::*pmf)(int*) const; 84 const A* pa; 85 86 B1() : pmf(&A::foo), pa(&a) {} 87 bool operator()() const { return (pa->*pmf)(new int); } 88 }; 89 90 void bar(B1 b2) { while (b2()) ; } 91} 92 93// PR5138 94namespace PR5138 { 95 struct foo { 96 virtual void bar(foo *); 97 }; 98 99 extern "C" { 100 void baz(foo *); 101 } 102 103 void (foo::*ptr1)(void *) = (void (foo::*)(void *))&foo::bar; 104 void (*ptr2)(void *) = (void (*)(void *))&baz; 105 106 void (foo::*ptr3)(void) = (void (foo::*)(void))&foo::bar; 107} 108 109// PR5593 110namespace PR5593 { 111 struct A { }; 112 113 bool f(void (A::*f)()) { 114 return f && f; 115 } 116} 117 118namespace PR5718 { 119 struct A { }; 120 121 bool f(void (A::*f)(), void (A::*g)()) { 122 return f == g; 123 } 124} 125 126namespace BoolMemberPointer { 127 struct A { }; 128 129 bool f(void (A::*f)()) { 130 return !f; 131 } 132 133 bool g(void (A::*f)()) { 134 if (!!f) 135 return true; 136 return false; 137 } 138} 139 140// PR5940 141namespace PR5940 { 142 class foo { 143 public: 144 virtual void baz(void); 145 }; 146 147 void foo::baz(void) { 148 void (foo::*ptr)(void) = &foo::baz; 149 } 150} 151 152namespace MemberPointerImpCast { 153 struct A { 154 int x; 155 }; 156 struct B : public A { 157 }; 158 void f(B* obj, void (A::*method)()) { 159 (obj->*method)(); 160 } 161} 162 163// PR6258 164namespace PR6258 { 165 166 struct A { 167 void f(bool); 168 }; 169 170 void (A::*pf)(bool) = &A::f; 171 172 void f() { 173 void (A::*pf)(bool) = &A::f; 174 } 175} 176 177// PR7027 178namespace PR7027 { 179 struct X { void test( ); }; 180 void testX() { &X::test; } 181} 182 183namespace test7 { 184 struct A { void foo(); virtual void vfoo(); }; 185 struct B { void foo(); virtual void vfoo(); }; 186 struct C : A, B { void foo(); virtual void vfoo(); }; 187 188 // CHECK-ARM: @_ZN5test74ptr0E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71A3fooEv to i32), i32 0 } 189 // CHECK-ARM: @_ZN5test74ptr1E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71B3fooEv to i32), i32 8 } 190 // CHECK-ARM: @_ZN5test74ptr2E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71C3fooEv to i32), i32 0 } 191 // CHECK-ARM: @_ZN5test74ptr3E = global {{.*}} { i32 0, i32 1 } 192 // CHECK-ARM: @_ZN5test74ptr4E = global {{.*}} { i32 0, i32 9 } 193 // CHECK-ARM: @_ZN5test74ptr5E = global {{.*}} { i32 0, i32 1 } 194 void (C::*ptr0)() = &A::foo; 195 void (C::*ptr1)() = &B::foo; 196 void (C::*ptr2)() = &C::foo; 197 void (C::*ptr3)() = &A::vfoo; 198 void (C::*ptr4)() = &B::vfoo; 199 void (C::*ptr5)() = &C::vfoo; 200} 201 202namespace test8 { 203 struct X { }; 204 typedef int (X::*pmf)(int); 205 206 // CHECK: {{define.*_ZN5test81fEv}} 207 pmf f() { 208 // CHECK: {{ret.*zeroinitializer}} 209 return pmf(); 210 } 211} 212 213namespace test9 { 214 struct A { 215 void foo(); 216 }; 217 struct B : A { 218 void foo(); 219 }; 220 221 typedef void (A::*fooptr)(); 222 223 struct S { 224 fooptr p; 225 }; 226 227 // CHECK: define void @_ZN5test94testEv( 228 // CHECK: alloca i32 229 // CHECK-NEXT: ret void 230 void test() { 231 int x; 232 static S array[] = { (fooptr) &B::foo }; 233 } 234} 235