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 noundef 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 noundef 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 noundef 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 noundef 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 noundef 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 noundef 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 noundef 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 noundef 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 noundef 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 noundef i32 @_ZN5Test81B3fooEv(ptr {{[^,]*}} %[[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: [[VTABLE:%.+]] = load {{.+}} 220 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0 221 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 222 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 223 return static_cast<RA*>(x)->f(); 224 } 225 // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE fop(RC * x)226 A *fop(RC *x) { 227 // FIXME: It should be possible to devirtualize this case, but that is 228 // not implemented yet. 229 // CHECK: load 230 // CHECK: [[VTABLE:%.+]] = load {{.+}} 231 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1 232 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 233 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 234 return -static_cast<RA&>(*x); 235 } 236 } 237 238 namespace Test10 { 239 struct A { 240 virtual int f(); 241 }; 242 243 struct B : A { 244 int f() final; 245 }; 246 247 // CHECK-LABEL: define{{.*}} i32 @_ZN6Test101fEPNS_1BE f(B * b)248 int f(B *b) { 249 // CHECK: call noundef i32 @_ZN6Test101B1fEv 250 return static_cast<A *>(b)->f(); 251 } 252 } 253 254 namespace TestVBase { 255 struct A { virtual void f(); }; 256 struct B : virtual A {}; 257 struct C : virtual A { void f() override; }; 258 259 extern struct BC final : B, C {} &bc; 260 extern struct BCusingA final : B, C { using A::f; } &bc_using_a; 261 extern struct BCusingB final : B, C { using B::f; } &bc_using_b; 262 extern struct BCusingC final : B, C { using C::f; } &bc_using_c; 263 264 extern struct CB final : C, B {} &cb; 265 extern struct CBusingA final : C, B { using A::f; } &cb_using_a; 266 extern struct CBusingB final : C, B { using B::f; } &cb_using_b; 267 extern struct CBusingC final : C, B { using C::f; } &cb_using_c; 268 269 // CHECK-LABEL: @_ZN9TestVBase4testEv( test()270 void test() { 271 // FIXME: The 'using A' case can be devirtualized to call A's virtual 272 // adjustment thunk for C::f. 273 // FIXME: The 'using B' case can be devirtualized, but requires us to emit 274 // a derived-to-base or base-to-derived conversion as part of 275 // devirtualization. 276 277 // CHECK: call void @_ZN9TestVBase1C1fEv( 278 bc.f(); 279 // CHECK: call void % 280 bc_using_a.f(); 281 // CHECK: call void % 282 bc_using_b.f(); 283 // CHECK: call void @_ZN9TestVBase1C1fEv( 284 bc_using_c.f(); 285 286 // CHECK: call void @_ZN9TestVBase1C1fEv( 287 cb.f(); 288 // CHECK: call void % 289 cb_using_a.f(); 290 // CHECK: call void % 291 cb_using_b.f(); 292 // CHECK: call void @_ZN9TestVBase1C1fEv( 293 cb_using_c.f(); 294 } 295 } 296 297 namespace Test11 { 298 // Check that the definitions of Derived's operators are emitted. 299 300 // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev( 301 // CHECK: call void @_ZN6Test111SIiE7DerivedclEv( 302 // CHECK: call noundef zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( 303 // CHECK: call noundef zeroext i1 @_ZN6Test111SIiE7DerivedntEv( 304 // CHECK: call noundef nonnull align 4 dereferenceable(4) ptr @_ZN6Test111SIiE7DerivedixEi( 305 // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv( 306 // CHECK: define linkonce_odr noundef zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( 307 // CHECK: define linkonce_odr noundef zeroext i1 @_ZN6Test111SIiE7DerivedntEv( 308 // CHECK: define linkonce_odr noundef nonnull align 4 dereferenceable(4) ptr @_ZN6Test111SIiE7DerivedixEi( 309 class Base { 310 public: operator ()()311 virtual void operator()() {} operator ==(const Base & other)312 virtual bool operator==(const Base &other) { return false; } operator !()313 virtual bool operator!() { return false; } operator [](int i)314 virtual Base &operator[](int i) { return *this; } 315 }; 316 317 template<class T> 318 struct S { 319 class Derived final : public Base { 320 public: operator ()()321 void operator()() override {} operator ==(const Base & other)322 bool operator==(const Base &other) override { return true; } operator !()323 bool operator!() override { return true; } operator [](int i)324 Base &operator[](int i) override { return *this; } 325 }; 326 327 Derived *ptr = nullptr, *ptr2 = nullptr; 328 foo1Test11::S329 void foo1() { 330 if (ptr && ptr2) { 331 // These calls get devirtualized. Linkage fails if the definitions of 332 // the called functions are not emitted. 333 (*ptr)(); 334 (void)(*ptr == *ptr2); 335 (void)(!(*ptr)); 336 (void)((*ptr)[1]); 337 } 338 } 339 }; 340 foo2()341 void foo2() { 342 S<int> *s = new S<int>; 343 s->foo1(); 344 } 345 } 346