Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
      2 // RUN: FileCheck %s < %t
      3 // RUN: FileCheck --check-prefix=BITCODE %s < %t.ll
      4 
      5 namespace test1 {
      6 struct 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 
     12 struct 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.
     17 struct 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: @"\01??_7X@test1@@6BA@1@@"
     33   // BITCODE-DAG: @"\01??_7X@test1@@6BB@1@@"
     34 
     35   virtual void g();
     36 } x;
     37 
     38 void build_vftable(X *obj) { obj->g(); }
     39 }
     40 
     41 namespace test2 {
     42 struct A {
     43   virtual void f();
     44 };
     45 
     46 struct B {
     47   virtual void g();
     48   virtual void h();
     49 };
     50 
     51 struct C {
     52   virtual void g();
     53 };
     54 
     55 struct 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 4
     72   // CHECK-NEXT:   0 | void test2::X::g()
     73 
     74   // BITCODE-DAG: @"\01??_7X@test2@@6BA@1@@"
     75   // BITCODE-DAG: @"\01??_7X@test2@@6BB@1@@"
     76   // BITCODE-DAG: @"\01??_7X@test2@@6BC@1@@"
     77 
     78   virtual void g();
     79 } x;
     80 
     81 void build_vftable(X *obj) { obj->g(); }
     82 }
     83 
     84 namespace test3 {
     85 struct A {
     86   virtual void f();
     87 };
     88 
     89 struct B {
     90   virtual void g();
     91   virtual void h();
     92 };
     93 
     94 struct C: A, B {
     95   // Overrides only the left child's method (A::f), needs no thunks.
     96   virtual void f();
     97 };
     98 
     99 struct 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.
    106 struct 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 0
    131   // CHECK-NEXT:   0 | void test3::X::f()
    132   // CHECK-NEXT:   via vfptr at offset 4
    133   // CHECK-NEXT:   0 | void test3::X::g()
    134 
    135   virtual void f();
    136   virtual void g();
    137 } x;
    138 
    139 void build_vftable(X *obj) { obj->g(); }
    140 }
    141 
    142 namespace test4 {
    143 struct A {
    144   virtual void foo();
    145 };
    146 struct B {
    147   virtual int filler();
    148   virtual int operator-();
    149   virtual int bar();
    150 };
    151 struct C : public A, public B {
    152   virtual int filler();
    153   virtual int operator-();
    154   virtual int bar();
    155 };
    156 
    157 // BITCODE-LABEL: define {{.*}}\01?ffun@test4@@YAXAAUC@1@@Z
    158 void ffun(C &c) {
    159   // BITCODE: load
    160   // BITCODE: bitcast
    161   // BITCODE: bitcast
    162   // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
    163   // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
    164   // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
    165   c.bar();
    166 }
    167 
    168 // BITCODE-LABEL: define {{.*}}\01?fop@test4@@YAXAAUC@1@@Z
    169 void fop(C &c) {
    170   // BITCODE: load
    171   // BITCODE: bitcast
    172   // BITCODE: bitcast
    173   // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
    174   // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
    175   // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]])
    176   -c;
    177 }
    178 
    179 }
    180