1 // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t 2 // RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll 3 // RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll 4 // RUN: FileCheck --check-prefix=CHECK-A %s < %t 5 // RUN: FileCheck --check-prefix=CHECK-B %s < %t 6 // RUN: FileCheck --check-prefix=CHECK-C %s < %t 7 // RUN: FileCheck --check-prefix=CHECK-D %s < %t 8 // RUN: FileCheck --check-prefix=CHECK-E %s < %t 9 // RUN: FileCheck --check-prefix=CHECK-F %s < %t 10 // RUN: FileCheck --check-prefix=CHECK-G %s < %t 11 // RUN: FileCheck --check-prefix=CHECK-I %s < %t 12 // RUN: FileCheck --check-prefix=CHECK-J %s < %t 13 // RUN: FileCheck --check-prefix=CHECK-K %s < %t 14 // RUN: FileCheck --check-prefix=CHECK-L %s < %t 15 // RUN: FileCheck --check-prefix=CHECK-M %s < %t 16 // RUN: FileCheck --check-prefix=CHECK-N %s < %t 17 // RUN: FileCheck --check-prefix=CHECK-O %s < %t 18 19 struct A { 20 // CHECK-A: VFTable for 'A' (3 entries) 21 // CHECK-A-NEXT: 0 | void A::f() 22 // CHECK-A-NEXT: 1 | void A::g() 23 // CHECK-A-NEXT: 2 | void A::h() 24 // CHECK-A: VFTable indices for 'A' (3 entries) 25 // CHECK-A-NEXT: 0 | void A::f() 26 // CHECK-A-NEXT: 1 | void A::g() 27 // CHECK-A-NEXT: 2 | void A::h() 28 29 virtual void f(); 30 virtual void g(); 31 virtual void h(); 32 int ia; 33 }; 34 A a; 35 // EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] 36 37 struct B : A { 38 // CHECK-B: VFTable for 'A' in 'B' (5 entries) 39 // CHECK-B-NEXT: 0 | void B::f() 40 // CHECK-B-NEXT: 1 | void A::g() 41 // CHECK-B-NEXT: 2 | void A::h() 42 // CHECK-B-NEXT: 3 | void B::i() 43 // CHECK-B-NEXT: 4 | void B::j() 44 // CHECK-B: VFTable indices for 'B' (3 entries) 45 // CHECK-B-NEXT: 0 | void B::f() 46 // CHECK-B-NEXT: 3 | void B::i() 47 // CHECK-B-NEXT: 4 | void B::j() 48 49 virtual void f(); // overrides A::f() 50 virtual void i(); 51 virtual void j(); 52 }; 53 B b; 54 // EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] 55 56 struct C { 57 // CHECK-C: VFTable for 'C' (2 entries) 58 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 59 // CHECK-C-NEXT: 1 | void C::f() 60 // CHECK-C: VFTable indices for 'C' (2 entries). 61 // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] 62 // CHECK-C-NEXT: 1 | void C::f() 63 64 virtual ~C(); 65 virtual void f(); 66 }; 67 void C::f() {} 68 // NO-VFTABLE-NOT: @"\01??_7C@@6B@" 69 70 struct D { 71 // CHECK-D: VFTable for 'D' (2 entries) 72 // CHECK-D-NEXT: 0 | void D::f() 73 // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] 74 // CHECK-D: VFTable indices for 'D' (2 entries) 75 // CHECK-D-NEXT: 0 | void D::f() 76 // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] 77 78 virtual void f(); 79 virtual ~D(); 80 }; 81 D d; 82 // EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] 83 84 struct E : A { 85 // CHECK-E: VFTable for 'A' in 'E' (5 entries) 86 // CHECK-E-NEXT: 0 | void A::f() 87 // CHECK-E-NEXT: 1 | void A::g() 88 // CHECK-E-NEXT: 2 | void A::h() 89 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 90 // CHECK-E-NEXT: 4 | void E::i() 91 // CHECK-E: VFTable indices for 'E' (2 entries). 92 // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] 93 // CHECK-E-NEXT: 4 | void E::i() 94 95 // ~E would be the key method, but it isn't used, and MS ABI has no key 96 // methods. 97 virtual ~E(); 98 virtual void i(); 99 }; 100 void E::i() {} 101 // NO-VFTABLE-NOT: @"\01??_7E@@6B@" 102 103 struct F : A { 104 // CHECK-F: VFTable for 'A' in 'F' (5 entries) 105 // CHECK-F-NEXT: 0 | void A::f() 106 // CHECK-F-NEXT: 1 | void A::g() 107 // CHECK-F-NEXT: 2 | void A::h() 108 // CHECK-F-NEXT: 3 | void F::i() 109 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 110 // CHECK-F: VFTable indices for 'F' (2 entries). 111 // CHECK-F-NEXT: 3 | void F::i() 112 // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] 113 114 virtual void i(); 115 virtual ~F(); 116 }; 117 F f; 118 // EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] 119 120 struct G : E { 121 // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries) 122 // CHECK-G-NEXT: 0 | void G::f() 123 // CHECK-G-NEXT: 1 | void A::g() 124 // CHECK-G-NEXT: 2 | void A::h() 125 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 126 // CHECK-G-NEXT: 4 | void E::i() 127 // CHECK-G-NEXT: 5 | void G::j() 128 // CHECK-G: VFTable indices for 'G' (3 entries). 129 // CHECK-G-NEXT: 0 | void G::f() 130 // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] 131 // CHECK-G-NEXT: 5 | void G::j() 132 133 virtual void f(); // overrides A::f() 134 virtual ~G(); 135 virtual void j(); 136 }; 137 void G::j() {} 138 // NO-VFTABLE-NOT: @"\01??_7G@@6B@" 139 140 // Test that the usual Itanium-style key method does not emit a vtable. 141 struct H { 142 virtual void f(); 143 }; 144 void H::f() {} 145 // NO-VFTABLE-NOT: @"\01??_7H@@6B@" 146 147 struct Empty { }; 148 149 struct I : Empty { 150 // CHECK-I: VFTable for 'I' (2 entries) 151 // CHECK-I-NEXT: 0 | void I::f() 152 // CHECK-I-NEXT: 1 | void I::g() 153 virtual void f(); 154 virtual void g(); 155 }; 156 157 I i; 158 159 struct J { 160 // CHECK-J: VFTable for 'J' (6 entries) 161 // CHECK-J-NEXT: 0 | void J::foo(long) 162 // CHECK-J-NEXT: 1 | void J::foo(int) 163 // CHECK-J-NEXT: 2 | void J::foo(short) 164 // CHECK-J-NEXT: 3 | void J::bar(long) 165 // CHECK-J-NEXT: 4 | void J::bar(int) 166 // CHECK-J-NEXT: 5 | void J::bar(short) 167 virtual void foo(short); 168 virtual void bar(short); 169 virtual void foo(int); 170 virtual void bar(int); 171 virtual void foo(long); 172 virtual void bar(long); 173 }; 174 175 J j; 176 177 struct K : J { 178 // CHECK-K: VFTable for 'J' in 'K' (9 entries) 179 // CHECK-K-NEXT: 0 | void J::foo(long) 180 // CHECK-K-NEXT: 1 | void J::foo(int) 181 // CHECK-K-NEXT: 2 | void J::foo(short) 182 // CHECK-K-NEXT: 3 | void J::bar(long) 183 // CHECK-K-NEXT: 4 | void J::bar(int) 184 // CHECK-K-NEXT: 5 | void J::bar(short) 185 // CHECK-K-NEXT: 6 | void K::bar(double) 186 // CHECK-K-NEXT: 7 | void K::bar(float) 187 // CHECK-K-NEXT: 8 | void K::foo(float) 188 virtual void bar(float); 189 virtual void foo(float); 190 virtual void bar(double); 191 }; 192 193 K k; 194 195 struct L : J { 196 // CHECK-L: VFTable for 'J' in 'L' (9 entries) 197 // CHECK-L-NEXT: 0 | void J::foo(long) 198 // CHECK-L-NEXT: 1 | void L::foo(int) 199 // CHECK-L-NEXT: 2 | void J::foo(short) 200 // CHECK-L-NEXT: 3 | void J::bar(long) 201 // CHECK-L-NEXT: 4 | void J::bar(int) 202 // CHECK-L-NEXT: 5 | void J::bar(short) 203 // CHECK-L-NEXT: 6 | void L::foo(float) 204 // CHECK-L-NEXT: 7 | void L::bar(double) 205 // CHECK-L-NEXT: 8 | void L::bar(float) 206 207 // This case is interesting. Since the J::foo(int) override is the first method in 208 // the class, foo(float) precedes the bar(double) and bar(float) in the vftable. 209 virtual void foo(int); 210 virtual void bar(float); 211 virtual void foo(float); 212 virtual void bar(double); 213 }; 214 215 L l; 216 217 struct M : J { 218 // CHECK-M: VFTable for 'J' in 'M' (11 entries) 219 // CHECK-M-NEXT: 0 | void J::foo(long) 220 // CHECK-M-NEXT: 1 | void M::foo(int) 221 // CHECK-M-NEXT: 2 | void J::foo(short) 222 // CHECK-M-NEXT: 3 | void J::bar(long) 223 // CHECK-M-NEXT: 4 | void J::bar(int) 224 // CHECK-M-NEXT: 5 | void J::bar(short) 225 // CHECK-M-NEXT: 6 | void M::foo(float) 226 // CHECK-M-NEXT: 7 | void M::spam(long) 227 // CHECK-M-NEXT: 8 | void M::spam(int) 228 // CHECK-M-NEXT: 9 | void M::bar(double) 229 // CHECK-M-NEXT: 10 | void M::bar(float) 230 231 virtual void foo(int); 232 virtual void spam(int); 233 virtual void bar(float); 234 virtual void bar(double); 235 virtual void foo(float); 236 virtual void spam(long); 237 }; 238 239 M m; 240 241 struct N { 242 // CHECK-N: VFTable for 'N' (4 entries) 243 // CHECK-N-NEXT: 0 | void N::operator+(int) 244 // CHECK-N-NEXT: 1 | void N::operator+(short) 245 // CHECK-N-NEXT: 2 | void N::operator*(int) 246 // CHECK-N-NEXT: 3 | void N::operator*(short) 247 virtual void operator+(short); 248 virtual void operator*(short); 249 virtual void operator+(int); 250 virtual void operator*(int); 251 }; 252 253 N n; 254 255 struct O { virtual A *f(); }; 256 struct P : O { virtual B *f(); }; 257 P p; 258 // CHECK-O: VFTable for 'O' in 'P' (1 entries) 259 // CHECK-O-NEXT: 0 | B *P::f() 260 261 // CHECK-O: VFTable for 'O' (1 entries) 262 // CHECK-O-NEXT: 0 | A *O::f() 263