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