1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-unknown-unknown | FileCheck -check-prefix CODE-LP64 %s 2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-unknown-unknown | FileCheck -check-prefix CODE-LP32 %s 3*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-unknown-unknown | FileCheck -check-prefix GLOBAL-LP64 %s 4*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-unknown-unknown | FileCheck -check-prefix GLOBAL-LP32 %s 5*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix GLOBAL-ARM %s 6*f4a2713aSLionel Sambuc 7*f4a2713aSLionel Sambuc // PNaCl uses the same representation of method pointers as ARM. 8*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=le32-unknown-nacl | FileCheck -check-prefix GLOBAL-ARM %s 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc struct A { int a; void f(); virtual void vf1(); virtual void vf2(); }; 11*f4a2713aSLionel Sambuc struct B { int b; virtual void g(); }; 12*f4a2713aSLionel Sambuc struct C : B, A { }; 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc void (A::*pa)(); 15*f4a2713aSLionel Sambuc void (A::*volatile vpa)(); 16*f4a2713aSLionel Sambuc void (B::*pb)(); 17*f4a2713aSLionel Sambuc void (C::*pc)(); 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc // GLOBAL-LP64: @pa2 = global { i64, i64 } { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }, align 8 20*f4a2713aSLionel Sambuc void (A::*pa2)() = &A::f; 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc // GLOBAL-LP64: @pa3 = global { i64, i64 } { i64 1, i64 0 }, align 8 23*f4a2713aSLionel Sambuc // GLOBAL-LP32: @pa3 = global { i32, i32 } { i32 1, i32 0 }, align 4 24*f4a2713aSLionel Sambuc void (A::*pa3)() = &A::vf1; 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc // GLOBAL-LP64: @pa4 = global { i64, i64 } { i64 9, i64 0 }, align 8 27*f4a2713aSLionel Sambuc // GLOBAL-LP32: @pa4 = global { i32, i32 } { i32 5, i32 0 }, align 4 28*f4a2713aSLionel Sambuc void (A::*pa4)() = &A::vf2; 29*f4a2713aSLionel Sambuc 30*f4a2713aSLionel Sambuc // GLOBAL-LP64: @pc2 = global { i64, i64 } { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 16 }, align 8 31*f4a2713aSLionel Sambuc void (C::*pc2)() = &C::f; 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc // GLOBAL-LP64: @pc3 = global { i64, i64 } { i64 1, i64 0 }, align 8 34*f4a2713aSLionel Sambuc void (A::*pc3)() = &A::vf1; 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc void f() { 37*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } zeroinitializer, { i64, i64 }* @pa 38*f4a2713aSLionel Sambuc pa = 0; 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc // Is this okay? What are LLVM's volatile semantics for structs? 41*f4a2713aSLionel Sambuc // CODE-LP64: store volatile { i64, i64 } zeroinitializer, { i64, i64 }* @vpa 42*f4a2713aSLionel Sambuc vpa = 0; 43*f4a2713aSLionel Sambuc 44*f4a2713aSLionel Sambuc // CODE-LP64: [[TMP:%.*]] = load { i64, i64 }* @pa, align 8 45*f4a2713aSLionel Sambuc // CODE-LP64: [[TMPADJ:%.*]] = extractvalue { i64, i64 } [[TMP]], 1 46*f4a2713aSLionel Sambuc // CODE-LP64: [[ADJ:%.*]] = add nsw i64 [[TMPADJ]], 16 47*f4a2713aSLionel Sambuc // CODE-LP64: [[RES:%.*]] = insertvalue { i64, i64 } [[TMP]], i64 [[ADJ]], 1 48*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } [[RES]], { i64, i64 }* @pc, align 8 49*f4a2713aSLionel Sambuc pc = pa; 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc // CODE-LP64: [[TMP:%.*]] = load { i64, i64 }* @pc, align 8 52*f4a2713aSLionel Sambuc // CODE-LP64: [[TMPADJ:%.*]] = extractvalue { i64, i64 } [[TMP]], 1 53*f4a2713aSLionel Sambuc // CODE-LP64: [[ADJ:%.*]] = sub nsw i64 [[TMPADJ]], 16 54*f4a2713aSLionel Sambuc // CODE-LP64: [[RES:%.*]] = insertvalue { i64, i64 } [[TMP]], i64 [[ADJ]], 1 55*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } [[RES]], { i64, i64 }* @pa, align 8 56*f4a2713aSLionel Sambuc pa = static_cast<void (A::*)()>(pc); 57*f4a2713aSLionel Sambuc } 58*f4a2713aSLionel Sambuc 59*f4a2713aSLionel Sambuc void f2() { 60*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 } 61*f4a2713aSLionel Sambuc void (A::*pa2)() = &A::f; 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } { i64 1, i64 0 } 64*f4a2713aSLionel Sambuc // CODE-LP32: store { i32, i32 } { i32 1, i32 0 } 65*f4a2713aSLionel Sambuc void (A::*pa3)() = &A::vf1; 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc // CODE-LP64: store { i64, i64 } { i64 9, i64 0 } 68*f4a2713aSLionel Sambuc // CODE-LP32: store { i32, i32 } { i32 5, i32 0 } 69*f4a2713aSLionel Sambuc void (A::*pa4)() = &A::vf2; 70*f4a2713aSLionel Sambuc } 71*f4a2713aSLionel Sambuc 72*f4a2713aSLionel Sambuc void f3(A *a, A &ar) { 73*f4a2713aSLionel Sambuc (a->*pa)(); 74*f4a2713aSLionel Sambuc (ar.*pa)(); 75*f4a2713aSLionel Sambuc } 76*f4a2713aSLionel Sambuc 77*f4a2713aSLionel Sambuc bool f4() { 78*f4a2713aSLionel Sambuc return pa; 79*f4a2713aSLionel Sambuc } 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc // PR5177 82*f4a2713aSLionel Sambuc namespace PR5177 { 83*f4a2713aSLionel Sambuc struct A { 84*f4a2713aSLionel Sambuc bool foo(int*) const; 85*f4a2713aSLionel Sambuc } a; 86*f4a2713aSLionel Sambuc 87*f4a2713aSLionel Sambuc struct B1 { 88*f4a2713aSLionel Sambuc bool (A::*pmf)(int*) const; 89*f4a2713aSLionel Sambuc const A* pa; 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc B1() : pmf(&A::foo), pa(&a) {} 92*f4a2713aSLionel Sambuc bool operator()() const { return (pa->*pmf)(new int); } 93*f4a2713aSLionel Sambuc }; 94*f4a2713aSLionel Sambuc 95*f4a2713aSLionel Sambuc void bar(B1 b2) { while (b2()) ; } 96*f4a2713aSLionel Sambuc } 97*f4a2713aSLionel Sambuc 98*f4a2713aSLionel Sambuc // PR5138 99*f4a2713aSLionel Sambuc namespace PR5138 { 100*f4a2713aSLionel Sambuc struct foo { 101*f4a2713aSLionel Sambuc virtual void bar(foo *); 102*f4a2713aSLionel Sambuc }; 103*f4a2713aSLionel Sambuc 104*f4a2713aSLionel Sambuc extern "C" { 105*f4a2713aSLionel Sambuc void baz(foo *); 106*f4a2713aSLionel Sambuc } 107*f4a2713aSLionel Sambuc 108*f4a2713aSLionel Sambuc void (foo::*ptr1)(void *) = (void (foo::*)(void *))&foo::bar; 109*f4a2713aSLionel Sambuc void (*ptr2)(void *) = (void (*)(void *))&baz; 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc void (foo::*ptr3)(void) = (void (foo::*)(void))&foo::bar; 112*f4a2713aSLionel Sambuc } 113*f4a2713aSLionel Sambuc 114*f4a2713aSLionel Sambuc // PR5593 115*f4a2713aSLionel Sambuc namespace PR5593 { 116*f4a2713aSLionel Sambuc struct A { }; 117*f4a2713aSLionel Sambuc 118*f4a2713aSLionel Sambuc bool f(void (A::*f)()) { 119*f4a2713aSLionel Sambuc return f && f; 120*f4a2713aSLionel Sambuc } 121*f4a2713aSLionel Sambuc } 122*f4a2713aSLionel Sambuc 123*f4a2713aSLionel Sambuc namespace PR5718 { 124*f4a2713aSLionel Sambuc struct A { }; 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc bool f(void (A::*f)(), void (A::*g)()) { 127*f4a2713aSLionel Sambuc return f == g; 128*f4a2713aSLionel Sambuc } 129*f4a2713aSLionel Sambuc } 130*f4a2713aSLionel Sambuc 131*f4a2713aSLionel Sambuc namespace BoolMemberPointer { 132*f4a2713aSLionel Sambuc struct A { }; 133*f4a2713aSLionel Sambuc 134*f4a2713aSLionel Sambuc bool f(void (A::*f)()) { 135*f4a2713aSLionel Sambuc return !f; 136*f4a2713aSLionel Sambuc } 137*f4a2713aSLionel Sambuc 138*f4a2713aSLionel Sambuc bool g(void (A::*f)()) { 139*f4a2713aSLionel Sambuc if (!!f) 140*f4a2713aSLionel Sambuc return true; 141*f4a2713aSLionel Sambuc return false; 142*f4a2713aSLionel Sambuc } 143*f4a2713aSLionel Sambuc } 144*f4a2713aSLionel Sambuc 145*f4a2713aSLionel Sambuc // PR5940 146*f4a2713aSLionel Sambuc namespace PR5940 { 147*f4a2713aSLionel Sambuc class foo { 148*f4a2713aSLionel Sambuc public: 149*f4a2713aSLionel Sambuc virtual void baz(void); 150*f4a2713aSLionel Sambuc }; 151*f4a2713aSLionel Sambuc 152*f4a2713aSLionel Sambuc void foo::baz(void) { 153*f4a2713aSLionel Sambuc void (foo::*ptr)(void) = &foo::baz; 154*f4a2713aSLionel Sambuc } 155*f4a2713aSLionel Sambuc } 156*f4a2713aSLionel Sambuc 157*f4a2713aSLionel Sambuc namespace MemberPointerImpCast { 158*f4a2713aSLionel Sambuc struct A { 159*f4a2713aSLionel Sambuc int x; 160*f4a2713aSLionel Sambuc }; 161*f4a2713aSLionel Sambuc struct B : public A { 162*f4a2713aSLionel Sambuc }; 163*f4a2713aSLionel Sambuc void f(B* obj, void (A::*method)()) { 164*f4a2713aSLionel Sambuc (obj->*method)(); 165*f4a2713aSLionel Sambuc } 166*f4a2713aSLionel Sambuc } 167*f4a2713aSLionel Sambuc 168*f4a2713aSLionel Sambuc // PR6258 169*f4a2713aSLionel Sambuc namespace PR6258 { 170*f4a2713aSLionel Sambuc 171*f4a2713aSLionel Sambuc struct A { 172*f4a2713aSLionel Sambuc void f(bool); 173*f4a2713aSLionel Sambuc }; 174*f4a2713aSLionel Sambuc 175*f4a2713aSLionel Sambuc void (A::*pf)(bool) = &A::f; 176*f4a2713aSLionel Sambuc 177*f4a2713aSLionel Sambuc void f() { 178*f4a2713aSLionel Sambuc void (A::*pf)(bool) = &A::f; 179*f4a2713aSLionel Sambuc } 180*f4a2713aSLionel Sambuc } 181*f4a2713aSLionel Sambuc 182*f4a2713aSLionel Sambuc // PR7027 183*f4a2713aSLionel Sambuc namespace PR7027 { 184*f4a2713aSLionel Sambuc struct X { void test( ); }; 185*f4a2713aSLionel Sambuc void testX() { &X::test; } 186*f4a2713aSLionel Sambuc } 187*f4a2713aSLionel Sambuc 188*f4a2713aSLionel Sambuc namespace test7 { 189*f4a2713aSLionel Sambuc struct A { void foo(); virtual void vfoo(); }; 190*f4a2713aSLionel Sambuc struct B { void foo(); virtual void vfoo(); }; 191*f4a2713aSLionel Sambuc struct C : A, B { void foo(); virtual void vfoo(); }; 192*f4a2713aSLionel Sambuc 193*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr0E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71A3fooEv to i32), i32 0 } 194*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr1E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71B3fooEv to i32), i32 8 } 195*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr2E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71C3fooEv to i32), i32 0 } 196*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr3E = global {{.*}} { i32 0, i32 1 } 197*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr4E = global {{.*}} { i32 0, i32 9 } 198*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN5test74ptr5E = global {{.*}} { i32 0, i32 1 } 199*f4a2713aSLionel Sambuc void (C::*ptr0)() = &A::foo; 200*f4a2713aSLionel Sambuc void (C::*ptr1)() = &B::foo; 201*f4a2713aSLionel Sambuc void (C::*ptr2)() = &C::foo; 202*f4a2713aSLionel Sambuc void (C::*ptr3)() = &A::vfoo; 203*f4a2713aSLionel Sambuc void (C::*ptr4)() = &B::vfoo; 204*f4a2713aSLionel Sambuc void (C::*ptr5)() = &C::vfoo; 205*f4a2713aSLionel Sambuc } 206*f4a2713aSLionel Sambuc 207*f4a2713aSLionel Sambuc namespace test8 { 208*f4a2713aSLionel Sambuc struct X { }; 209*f4a2713aSLionel Sambuc typedef int (X::*pmf)(int); 210*f4a2713aSLionel Sambuc 211*f4a2713aSLionel Sambuc // CHECK: {{define.*_ZN5test81fEv}} 212*f4a2713aSLionel Sambuc pmf f() { 213*f4a2713aSLionel Sambuc // CHECK: {{ret.*zeroinitializer}} 214*f4a2713aSLionel Sambuc return pmf(); 215*f4a2713aSLionel Sambuc } 216*f4a2713aSLionel Sambuc } 217*f4a2713aSLionel Sambuc 218*f4a2713aSLionel Sambuc namespace test9 { 219*f4a2713aSLionel Sambuc struct A { 220*f4a2713aSLionel Sambuc void foo(); 221*f4a2713aSLionel Sambuc }; 222*f4a2713aSLionel Sambuc struct B : A { 223*f4a2713aSLionel Sambuc void foo(); 224*f4a2713aSLionel Sambuc }; 225*f4a2713aSLionel Sambuc 226*f4a2713aSLionel Sambuc typedef void (A::*fooptr)(); 227*f4a2713aSLionel Sambuc 228*f4a2713aSLionel Sambuc struct S { 229*f4a2713aSLionel Sambuc fooptr p; 230*f4a2713aSLionel Sambuc }; 231*f4a2713aSLionel Sambuc 232*f4a2713aSLionel Sambuc // CODE-LP64-LABEL: define void @_ZN5test94testEv( 233*f4a2713aSLionel Sambuc // CODE-LP64: alloca i32 234*f4a2713aSLionel Sambuc // CODE-LP64-NEXT: ret void 235*f4a2713aSLionel Sambuc void test() { 236*f4a2713aSLionel Sambuc int x; 237*f4a2713aSLionel Sambuc static S array[] = { (fooptr) &B::foo }; 238*f4a2713aSLionel Sambuc } 239*f4a2713aSLionel Sambuc } 240*f4a2713aSLionel Sambuc 241*f4a2713aSLionel Sambuc // rdar://problem/10815683 - Verify that we can emit reinterprets of 242*f4a2713aSLionel Sambuc // member pointers as constant initializers. For added trickiness, 243*f4a2713aSLionel Sambuc // we also add some non-trivial adjustments. 244*f4a2713aSLionel Sambuc namespace test10 { 245*f4a2713aSLionel Sambuc struct A { 246*f4a2713aSLionel Sambuc int nonEmpty; 247*f4a2713aSLionel Sambuc void foo(); 248*f4a2713aSLionel Sambuc }; 249*f4a2713aSLionel Sambuc struct B : public A { 250*f4a2713aSLionel Sambuc virtual void requireNonZeroAdjustment(); 251*f4a2713aSLionel Sambuc }; 252*f4a2713aSLionel Sambuc struct C { 253*f4a2713aSLionel Sambuc int nonEmpty; 254*f4a2713aSLionel Sambuc }; 255*f4a2713aSLionel Sambuc struct D : public C { 256*f4a2713aSLionel Sambuc virtual void requireNonZeroAdjustment(); 257*f4a2713aSLionel Sambuc }; 258*f4a2713aSLionel Sambuc 259*f4a2713aSLionel Sambuc 260*f4a2713aSLionel Sambuc // It's not that the offsets are doubled on ARM, it's that they're left-shifted by 1. 261*f4a2713aSLionel Sambuc 262*f4a2713aSLionel Sambuc // GLOBAL-LP64: @_ZN6test101aE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 0 }, align 8 263*f4a2713aSLionel Sambuc // GLOBAL-LP32: @_ZN6test101aE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 0 }, align 4 264*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN6test101aE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 0 }, align 4 265*f4a2713aSLionel Sambuc void (A::*a)() = &A::foo; 266*f4a2713aSLionel Sambuc 267*f4a2713aSLionel Sambuc // GLOBAL-LP64: @_ZN6test101bE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 8 }, align 8 268*f4a2713aSLionel Sambuc // GLOBAL-LP32: @_ZN6test101bE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 4 }, align 4 269*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN6test101bE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4 270*f4a2713aSLionel Sambuc void (B::*b)() = (void (B::*)()) &A::foo; 271*f4a2713aSLionel Sambuc 272*f4a2713aSLionel Sambuc // GLOBAL-LP64: @_ZN6test101cE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 8 }, align 8 273*f4a2713aSLionel Sambuc // GLOBAL-LP32: @_ZN6test101cE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 4 }, align 4 274*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN6test101cE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4 275*f4a2713aSLionel Sambuc void (C::*c)() = (void (C::*)()) (void (B::*)()) &A::foo; 276*f4a2713aSLionel Sambuc 277*f4a2713aSLionel Sambuc // GLOBAL-LP64: @_ZN6test101dE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 16 }, align 8 278*f4a2713aSLionel Sambuc // GLOBAL-LP32: @_ZN6test101dE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4 279*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN6test101dE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 16 }, align 4 280*f4a2713aSLionel Sambuc void (D::*d)() = (void (C::*)()) (void (B::*)()) &A::foo; 281*f4a2713aSLionel Sambuc } 282*f4a2713aSLionel Sambuc 283*f4a2713aSLionel Sambuc namespace test11 { 284*f4a2713aSLionel Sambuc struct A { virtual void a(); }; 285*f4a2713aSLionel Sambuc struct B : A {}; 286*f4a2713aSLionel Sambuc struct C : B { virtual void a(); }; 287*f4a2713aSLionel Sambuc void (C::*x)() = &C::a; 288*f4a2713aSLionel Sambuc 289*f4a2713aSLionel Sambuc // GLOBAL-LP64: @_ZN6test111xE = global { i64, i64 } { i64 1, i64 0 } 290*f4a2713aSLionel Sambuc // GLOBAL-LP32: @_ZN6test111xE = global { i32, i32 } { i32 1, i32 0 } 291*f4a2713aSLionel Sambuc // GLOBAL-ARM: @_ZN6test111xE = global { i32, i32 } { i32 0, i32 1 } 292*f4a2713aSLionel Sambuc } 293