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