1 // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s 2 3 namespace Test1 { 4 struct A { 5 virtual int f() final; 6 }; 7 8 // CHECK-LABEL: define i32 @_ZN5Test11fEPNS_1AE f(A * a)9 int f(A *a) { 10 // CHECK: call i32 @_ZN5Test11A1fEv 11 return a->f(); 12 } 13 } 14 15 namespace Test2 { 16 struct A final { 17 virtual int f(); 18 }; 19 20 // CHECK-LABEL: define i32 @_ZN5Test21fEPNS_1AE f(A * a)21 int f(A *a) { 22 // CHECK: call i32 @_ZN5Test21A1fEv 23 return a->f(); 24 } 25 } 26 27 namespace Test2a { 28 struct A { ~ATest2a::A29 virtual ~A() final {} 30 virtual int f(); 31 }; 32 33 // CHECK-LABEL: define i32 @_ZN6Test2a1fEPNS_1AE f(A * a)34 int f(A *a) { 35 // CHECK: call i32 @_ZN6Test2a1A1fEv 36 return a->f(); 37 } 38 } 39 40 41 namespace Test3 { 42 struct A { 43 virtual int f(); }; 44 45 struct B final : A { }; 46 47 // CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE f(B * b)48 int f(B *b) { 49 // CHECK: call i32 @_ZN5Test31A1fEv 50 return b->f(); 51 } 52 53 // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE f(B & b)54 int f(B &b) { 55 // CHECK: call i32 @_ZN5Test31A1fEv 56 return b.f(); 57 } 58 59 // CHECK-LABEL: define i32 @_ZN5Test31fEPv f(void * v)60 int f(void *v) { 61 // CHECK: call i32 @_ZN5Test31A1fEv 62 return static_cast<B*>(v)->f(); 63 } 64 } 65 66 namespace Test4 { 67 struct A { 68 virtual void f(); 69 virtual int operator-(); 70 }; 71 72 struct B final : A { 73 virtual void f(); 74 virtual int operator-(); 75 }; 76 77 // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE f(B * d)78 void f(B* d) { 79 // CHECK: call void @_ZN5Test41B1fEv 80 static_cast<A*>(d)->f(); 81 // CHECK: call i32 @_ZN5Test41BngEv 82 -static_cast<A&>(*d); 83 } 84 } 85 86 namespace Test5 { 87 struct A { 88 virtual void f(); 89 virtual int operator-(); 90 }; 91 92 struct B : A { 93 virtual void f(); 94 virtual int operator-(); 95 }; 96 97 struct C final : B { 98 }; 99 100 // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE f(C * d)101 void f(C* d) { 102 // FIXME: It should be possible to devirtualize this case, but that is 103 // not implemented yet. 104 // CHECK: getelementptr 105 // CHECK-NEXT: %[[FUNC:.*]] = load 106 // CHECK-NEXT: call void %[[FUNC]] 107 static_cast<A*>(d)->f(); 108 } 109 // CHECK-LABEL: define void @_ZN5Test53fopEPNS_1CE fop(C * d)110 void fop(C* d) { 111 // FIXME: It should be possible to devirtualize this case, but that is 112 // not implemented yet. 113 // CHECK: getelementptr 114 // CHECK-NEXT: %[[FUNC:.*]] = load 115 // CHECK-NEXT: call i32 %[[FUNC]] 116 -static_cast<A&>(*d); 117 } 118 } 119 120 namespace Test6 { 121 struct A { 122 virtual ~A(); 123 }; 124 125 struct B : public A { 126 virtual ~B(); 127 }; 128 129 struct C { 130 virtual ~C(); 131 }; 132 133 struct D final : public C, public B { 134 }; 135 136 // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE f(D * d)137 void f(D* d) { 138 // CHECK: call void @_ZN5Test61DD1Ev 139 static_cast<A*>(d)->~A(); 140 } 141 } 142 143 namespace Test7 { 144 struct foo { gTest7::foo145 virtual void g() {} 146 }; 147 148 struct bar { fTest7::bar149 virtual int f() { return 0; } 150 }; 151 152 struct zed final : public foo, public bar { 153 int z; fTest7::zed154 virtual int f() {return z;} 155 }; 156 157 // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE f(zed * z)158 int f(zed *z) { 159 // CHECK: alloca 160 // CHECK-NEXT: store 161 // CHECK-NEXT: load 162 // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv 163 // CHECK-NEXT: ret 164 return static_cast<bar*>(z)->f(); 165 } 166 } 167 168 namespace Test8 { ~ATest8::A169 struct A { virtual ~A() {} }; 170 struct B { 171 int b; fooTest8::B172 virtual int foo() { return b; } 173 }; 174 struct C final : A, B { }; 175 // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE test(C * c)176 int test(C *c) { 177 // CHECK: %[[THIS:.*]] = phi 178 // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* {{[^,]*}} %[[THIS]]) 179 return static_cast<B*>(c)->foo(); 180 } 181 } 182 183 namespace Test9 { 184 struct A { 185 int a; 186 }; 187 struct B { 188 int b; 189 }; 190 struct C : public B, public A { 191 }; 192 struct RA { fTest9::RA193 virtual A *f() { 194 return 0; 195 } operator -Test9::RA196 virtual A *operator-() { 197 return 0; 198 } 199 }; 200 struct RC final : public RA { fTest9::RC201 virtual C *f() { 202 C *x = new C(); 203 x->a = 1; 204 x->b = 2; 205 return x; 206 } operator -Test9::RC207 virtual C *operator-() { 208 C *x = new C(); 209 x->a = 1; 210 x->b = 2; 211 return x; 212 } 213 }; 214 // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE f(RC * x)215 A *f(RC *x) { 216 // FIXME: It should be possible to devirtualize this case, but that is 217 // not implemented yet. 218 // CHECK: load 219 // CHECK: bitcast 220 // CHECK: [[F_PTR_RA:%.+]] = bitcast 221 // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] 222 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0 223 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 224 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 225 return static_cast<RA*>(x)->f(); 226 } 227 // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE fop(RC * x)228 A *fop(RC *x) { 229 // FIXME: It should be possible to devirtualize this case, but that is 230 // not implemented yet. 231 // CHECK: load 232 // CHECK: bitcast 233 // CHECK: [[F_PTR_RA:%.+]] = bitcast 234 // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] 235 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1 236 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 237 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 238 return -static_cast<RA&>(*x); 239 } 240 } 241 242 namespace Test10 { 243 struct A { 244 virtual int f(); 245 }; 246 247 struct B : A { 248 int f() final; 249 }; 250 251 // CHECK-LABEL: define i32 @_ZN6Test101fEPNS_1BE f(B * b)252 int f(B *b) { 253 // CHECK: call i32 @_ZN6Test101B1fEv 254 return static_cast<A *>(b)->f(); 255 } 256 } 257 258 namespace TestVBase { 259 struct A { virtual void f(); }; 260 struct B : virtual A {}; 261 struct C : virtual A { void f() override; }; 262 263 extern struct BC final : B, C {} &bc; 264 extern struct BCusingA final : B, C { using A::f; } &bc_using_a; 265 extern struct BCusingB final : B, C { using B::f; } &bc_using_b; 266 extern struct BCusingC final : B, C { using C::f; } &bc_using_c; 267 268 extern struct CB final : C, B {} &cb; 269 extern struct CBusingA final : C, B { using A::f; } &cb_using_a; 270 extern struct CBusingB final : C, B { using B::f; } &cb_using_b; 271 extern struct CBusingC final : C, B { using C::f; } &cb_using_c; 272 273 // CHECK-LABEL: @_ZN9TestVBase4testEv( test()274 void test() { 275 // FIXME: The 'using A' case can be devirtualized to call A's virtual 276 // adjustment thunk for C::f. 277 // FIXME: The 'using B' case can be devirtualized, but requires us to emit 278 // a derived-to-base or base-to-derived conversion as part of 279 // devirtualization. 280 281 // CHECK: call void @_ZN9TestVBase1C1fEv( 282 bc.f(); 283 // CHECK: call void % 284 bc_using_a.f(); 285 // CHECK: call void % 286 bc_using_b.f(); 287 // CHECK: call void @_ZN9TestVBase1C1fEv( 288 bc_using_c.f(); 289 290 // CHECK: call void @_ZN9TestVBase1C1fEv( 291 cb.f(); 292 // CHECK: call void % 293 cb_using_a.f(); 294 // CHECK: call void % 295 cb_using_b.f(); 296 // CHECK: call void @_ZN9TestVBase1C1fEv( 297 cb_using_c.f(); 298 } 299 } 300 301 namespace Test11 { 302 // Check that the definitions of Derived's operators are emitted. 303 304 // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev( 305 // CHECK: call void @_ZN6Test111SIiE7DerivedclEv( 306 // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( 307 // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedntEv( 308 // CHECK: call nonnull align 4 dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi( 309 // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv( 310 // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( 311 // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedntEv( 312 // CHECK: define linkonce_odr nonnull align 4 dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi( 313 class Base { 314 public: operator ()()315 virtual void operator()() {} operator ==(const Base & other)316 virtual bool operator==(const Base &other) { return false; } operator !()317 virtual bool operator!() { return false; } operator [](int i)318 virtual Base &operator[](int i) { return *this; } 319 }; 320 321 template<class T> 322 struct S { 323 class Derived final : public Base { 324 public: operator ()()325 void operator()() override {} operator ==(const Base & other)326 bool operator==(const Base &other) override { return true; } operator !()327 bool operator!() override { return true; } operator [](int i)328 Base &operator[](int i) override { return *this; } 329 }; 330 331 Derived *ptr = nullptr, *ptr2 = nullptr; 332 foo1Test11::S333 void foo1() { 334 if (ptr && ptr2) { 335 // These calls get devirtualized. Linkage fails if the definitions of 336 // the called functions are not emitted. 337 (*ptr)(); 338 (void)(*ptr == *ptr2); 339 (void)(!(*ptr)); 340 (void)((*ptr)[1]); 341 } 342 } 343 }; 344 foo2()345 void foo2() { 346 S<int> *s = new S<int>; 347 s->foo1(); 348 } 349 } 350