brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 931b60d Raw
346 lines · cpp
1// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s2 3namespace Test1 {4  struct A {5    virtual int f() final;6  };7 8  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test11fEPNS_1AE9  int f(A *a) {10    // CHECK: call noundef i32 @_ZN5Test11A1fEv11    return a->f();12  }13}14 15namespace Test2 {16  struct A final {17    virtual int f();18  };19 20  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test21fEPNS_1AE21  int f(A *a) {22    // CHECK: call noundef i32 @_ZN5Test21A1fEv23    return a->f();24  }25}26 27namespace Test2a {28  struct A {29    virtual ~A() final {}30    virtual int f();31  };32 33  // CHECK-LABEL: define{{.*}} i32 @_ZN6Test2a1fEPNS_1AE34  int f(A *a) {35    // CHECK: call noundef i32 @_ZN6Test2a1A1fEv36    return a->f();37  }38}39 40 41namespace Test3 {42  struct A {43    virtual int f();  };44 45  struct B final : A { };46 47  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fEPNS_1BE48  int f(B *b) {49    // CHECK: call noundef i32 @_ZN5Test31A1fEv50    return b->f();51  }52 53  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fERNS_1BE54  int f(B &b) {55    // CHECK: call noundef i32 @_ZN5Test31A1fEv56    return b.f();57  }58 59  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fEPv60  int f(void *v) {61    // CHECK: call noundef i32 @_ZN5Test31A1fEv62    return static_cast<B*>(v)->f();63  }64}65 66namespace 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_1BE78  void f(B* d) {79    // CHECK: call void @_ZN5Test41B1fEv80    static_cast<A*>(d)->f();81    // CHECK: call noundef i32 @_ZN5Test41BngEv82    -static_cast<A&>(*d);83  }84}85 86namespace 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_1CE101  void f(C* d) {102    // FIXME: It should be possible to devirtualize this case, but that is103    // not implemented yet.104    // CHECK: getelementptr105    // CHECK-NEXT: %[[FUNC:.*]] = load106    // CHECK-NEXT: call void %[[FUNC]]107    static_cast<A*>(d)->f();108  }109  // CHECK-LABEL: define{{.*}} void @_ZN5Test53fopEPNS_1CE110  void fop(C* d) {111    // FIXME: It should be possible to devirtualize this case, but that is112    // not implemented yet.113    // CHECK: getelementptr114    // CHECK-NEXT: %[[FUNC:.*]] = load115    // CHECK-NEXT: call noundef i32 %[[FUNC]]116    -static_cast<A&>(*d);117  }118}119 120namespace 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_1DE137  void f(D* d) {138    // CHECK: call void @_ZN5Test61DD1Ev139    static_cast<A*>(d)->~A();140  }141}142 143namespace Test7 {144  struct foo {145    virtual void g() {}146  };147 148  struct bar {149    virtual int f() { return 0; }150  };151 152  struct zed final : public foo, public bar {153    int z;154    virtual int f() {return z;}155  };156 157  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test71fEPNS_3zedE158  int f(zed *z) {159    // CHECK: alloca160    // CHECK-NEXT: store161    // CHECK-NEXT: load162    // CHECK-NEXT: call noundef i32 @_ZN5Test73zed1fEv163    // CHECK-NEXT: ret164    return static_cast<bar*>(z)->f();165  }166}167 168namespace Test8 {169  struct A { virtual ~A() {} };170  struct B {171    int b;172    virtual int foo() { return b; }173  };174  struct C final : A, B {  };175  // CHECK-LABEL: define{{.*}} i32 @_ZN5Test84testEPNS_1CE176  int test(C *c) {177    // CHECK: %[[THIS:.*]] = phi178    // CHECK-NEXT: call noundef i32 @_ZN5Test81B3fooEv(ptr {{[^,]*}} %[[THIS]])179    return static_cast<B*>(c)->foo();180  }181}182 183namespace 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 {193    virtual A *f() {194      return 0;195    }196    virtual A *operator-() {197      return 0;198    }199  };200  struct RC final : public RA {201    virtual C *f() {202      C *x = new C();203      x->a = 1;204      x->b = 2;205      return x;206    }207    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_2RCE215  A *f(RC *x) {216    // FIXME: It should be possible to devirtualize this case, but that is217    // not implemented yet.218    // CHECK: load219    // CHECK: [[VTABLE:%.+]] = load {{.+}}220    // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0221    // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]222    // CHECK-NEXT: = call {{.*}} %[[FUNC]]223    return static_cast<RA*>(x)->f();224  }225  // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE226  A *fop(RC *x) {227    // FIXME: It should be possible to devirtualize this case, but that is228    // not implemented yet.229    // CHECK: load230    // CHECK: [[VTABLE:%.+]] = load {{.+}}231    // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1232    // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]233    // CHECK-NEXT: = call {{.*}} %[[FUNC]]234    return -static_cast<RA&>(*x);235  }236}237 238namespace 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_1BE248  int f(B *b) {249    // CHECK: call noundef i32 @_ZN6Test101B1fEv250    return static_cast<A *>(b)->f();251  }252}253 254namespace 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(270  void test() {271    // FIXME: The 'using A' case can be devirtualized to call A's virtual272    // adjustment thunk for C::f.273    // FIXME: The 'using B' case can be devirtualized, but requires us to emit274    // a derived-to-base or base-to-derived conversion as part of275    // 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 297namespace 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:311    virtual void operator()() {}312    virtual bool operator==(const Base &other) { return false; }313    virtual bool operator!() { return false; }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:321      void operator()() override {}322      bool operator==(const Base &other) override { return true; }323      bool operator!() override { return true; }324      Base &operator[](int i) override { return *this; }325    };326 327    Derived *ptr = nullptr, *ptr2 = nullptr;328 329    void foo1() {330      if (ptr && ptr2) {331        // These calls get devirtualized. Linkage fails if the definitions of332        // the called functions are not emitted.333        (*ptr)();334        (void)(*ptr == *ptr2);335        (void)(!(*ptr));336        (void)((*ptr)[1]);337      }338    }339  };340 341  void foo2() {342    S<int> *s = new S<int>;343    s->foo1();344  }345}346