brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · d18dfa4 Raw
196 lines · cpp
1// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t2// RUN: FileCheck %s < %t3// RUN: FileCheck --check-prefix=BITCODE %s < %t.ll4 5namespace test1 {6struct A {7  virtual void g();8  // Add an extra virtual method so it's easier to check for the absence of thunks.9  virtual void h();10};11 12struct B {13  virtual void g();  // Collides with A::g if both are bases of some class.14};15 16// Overrides methods of two bases at the same time, thus needing thunks.17struct X : A, B {18  // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (2 entries).19  // CHECK-NEXT:   0 | void test1::X::g()20  // CHECK-NEXT:   1 | void test1::A::h()21 22  // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (1 entry).23  // CHECK-NEXT:   0 | void test1::X::g()24  // CHECK-NEXT:       [this adjustment: -4 non-virtual]25 26  // CHECK-LABEL: Thunks for 'void test1::X::g()' (1 entry).27  // CHECK-NEXT:   0 | [this adjustment: -4 non-virtual]28 29  // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).30  // CHECK-NEXT:   0 | void test1::X::g()31 32  // BITCODE-DAG: @"??_7X@test1@@6BA@1@@"33  // BITCODE-DAG: @"??_7X@test1@@6BB@1@@"34 35  virtual void g();36} x;37 38void build_vftable(X *obj) { obj->g(); }39}40 41namespace test2 {42struct A {43  virtual void f();44};45 46struct B {47  virtual void g();48  virtual void h();49};50 51struct C {52  virtual void g();53};54 55struct X : A, B, C {56  // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry).57  // CHECK-NEXT:   0 | void test2::A::f()58 59  // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries).60  // CHECK-NEXT:   0 | void test2::X::g()61  // CHECK-NEXT:   1 | void test2::B::h()62 63  // CHECK-LABEL: VFTable for 'test2::C' in 'test2::X' (1 entry).64  // CHECK-NEXT:   0 | void test2::X::g()65  // CHECK-NEXT:       [this adjustment: -4 non-virtual]66 67  // CHECK-LABEL: Thunks for 'void test2::X::g()' (1 entry).68  // CHECK-NEXT:   0 | [this adjustment: -4 non-virtual]69 70  // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).71  // CHECK-NEXT:   via vfptr at offset 472  // CHECK-NEXT:   0 | void test2::X::g()73 74  // BITCODE-DAG: @"??_7X@test2@@6BA@1@@"75  // BITCODE-DAG: @"??_7X@test2@@6BB@1@@"76  // BITCODE-DAG: @"??_7X@test2@@6BC@1@@"77 78  virtual void g();79} x;80 81void build_vftable(X *obj) { obj->g(); }82}83 84namespace test3 {85struct A {86  virtual void f();87};88 89struct B {90  virtual void g();91  virtual void h();92};93 94struct C: A, B {95  // Overrides only the left child's method (A::f), needs no thunks.96  virtual void f();97};98 99struct D: A, B {100  // Overrides only the right child's method (B::g),101  // needs this adjustment but not thunks.102  virtual void g();103};104 105// Overrides methods of two bases at the same time, thus needing thunks.106struct X: C, D {107  // CHECK-LABEL: VFTable for 'test3::A' in 'test3::C' in 'test3::X' (1 entry).108  // CHECK-NEXT:   0 | void test3::X::f()109 110  // CHECK-LABEL: VFTable for 'test3::B' in 'test3::C' in 'test3::X' (2 entries).111  // CHECK-NEXT:   0 | void test3::X::g()112  // CHECK-NEXT:   1 | void test3::B::h()113 114  // CHECK-LABEL: VFTable for 'test3::A' in 'test3::D' in 'test3::X' (1 entry).115  // CHECK-NEXT:   0 | void test3::X::f()116  // CHECK-NEXT:       [this adjustment: -8 non-virtual]117 118  // CHECK-LABEL: Thunks for 'void test3::X::f()' (1 entry).119  // CHECK-NEXT:   0 | [this adjustment: -8 non-virtual]120 121  // CHECK-LABEL: VFTable for 'test3::B' in 'test3::D' in 'test3::X' (2 entries).122  // CHECK-NEXT:   0 | void test3::X::g()123  // CHECK-NEXT:       [this adjustment: -8 non-virtual]124  // CHECK-NEXT:   1 | void test3::B::h()125 126  // CHECK-LABEL: Thunks for 'void test3::X::g()' (1 entry).127  // CHECK-NEXT:   0 | [this adjustment: -8 non-virtual]128 129  // CHECK-LABEL: VFTable indices for 'test3::X' (2 entries).130  // CHECK-NEXT:   via vfptr at offset 0131  // CHECK-NEXT:   0 | void test3::X::f()132  // CHECK-NEXT:   via vfptr at offset 4133  // CHECK-NEXT:   0 | void test3::X::g()134 135  virtual void f();136  virtual void g();137} x;138 139void build_vftable(X *obj) { obj->g(); }140}141 142namespace test4 {143struct A {144  virtual void foo();145};146struct B {147  virtual int filler();148  virtual int operator-();149  virtual int bar();150};151struct C : public A, public B {152  virtual int filler();153  virtual int operator-();154  virtual int bar();155};156 157// BITCODE-LABEL: define {{.*}}"?ffun@test4@@YAXAAUC@1@@Z158void ffun(C &c) {159  // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, ptr {{.*}}, i32 4160  // BITCODE: call x86_thiscallcc {{.*}}(ptr noundef [[THIS2]])161  c.bar();162}163 164// BITCODE-LABEL: define {{.*}}"?fop@test4@@YAXAAUC@1@@Z165void fop(C &c) {166  // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, ptr {{.*}}, i32 4167  // BITCODE: call x86_thiscallcc {{.*}}(ptr noundef [[THIS2]])168  -c;169}170 171}172 173namespace pr30293 {174struct NonTrivial {175  ~NonTrivial();176  int x;177};178struct A { virtual void f(); };179struct B { virtual void __cdecl g(NonTrivial); };180struct C final : A, B {181  void f() override;182  void __cdecl g(NonTrivial) override;183};184C *whatsthis;185void C::f() { g(NonTrivial()); }186void C::g(NonTrivial o) {187  whatsthis = this;188}189 190// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(ptr inalloca(<{ ptr, %"struct.pr30293::NonTrivial" }>) %0)191// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds nuw <{ ptr, %"struct.pr30293::NonTrivial" }>, ptr {{.*}}, i32 0, i32 0192// BITCODE: %[[this1:[^ ]*]] = load ptr, ptr %[[thisaddr]], align 4193// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, ptr %[[this1]], i32 -4194// BITCODE: store ptr %[[this3]], ptr @"?whatsthis@pr30293@@3PAUC@1@A", align 4195}196