1 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s 2 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s 3 4 namespace Test1 { 5 6 // Check that we emit a non-virtual thunk for C::f. 7 8 struct A { 9 virtual void f(); 10 }; 11 12 struct B { 13 virtual void f(); 14 }; 15 16 struct C : A, B { 17 virtual void c(); 18 19 virtual void f(); 20 }; 21 22 // CHECK: define void @_ZThn8_N5Test11C1fEv( 23 void C::f() { } 24 25 } 26 27 namespace Test2 { 28 29 // Check that we emit a thunk for B::f since it's overriding a virtual base. 30 31 struct A { 32 virtual void f(); 33 }; 34 35 struct B : virtual A { 36 virtual void b(); 37 virtual void f(); 38 }; 39 40 // CHECK: define void @_ZTv0_n24_N5Test21B1fEv( 41 void B::f() { } 42 43 } 44 45 namespace Test3 { 46 47 // Check that we emit a covariant thunk for B::f. 48 49 struct V1 { }; 50 struct V2 : virtual V1 { }; 51 52 struct A { 53 virtual V1 *f(); 54 }; 55 56 struct B : A { 57 virtual void b(); 58 59 virtual V2 *f(); 60 }; 61 62 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv( 63 V2 *B::f() { return 0; } 64 65 } 66 67 namespace Test4 { 68 69 // Check that the thunk for 'C::f' has the same visibility as the function itself. 70 71 struct A { 72 virtual void f(); 73 }; 74 75 struct B { 76 virtual void f(); 77 }; 78 79 struct __attribute__((visibility("protected"))) C : A, B { 80 virtual void c(); 81 82 virtual void f(); 83 }; 84 85 // CHECK: define protected void @_ZThn8_N5Test41C1fEv( 86 void C::f() { } 87 88 } 89 90 // Check that the thunk gets internal linkage. 91 namespace { 92 93 struct A { 94 virtual void f(); 95 }; 96 97 struct B { 98 virtual void f(); 99 }; 100 101 struct C : A, B { 102 virtual void c(); 103 104 virtual void f(); 105 }; 106 107 void C::f() { } 108 109 } 110 111 // Force C::f to be used. 112 void f() { 113 C c; 114 115 c.f(); 116 } 117 118 namespace Test5 { 119 120 // Check that the thunk for 'B::f' gets the same linkage as the function itself. 121 struct A { 122 virtual void f(); 123 }; 124 125 struct B : virtual A { 126 virtual void f() { } 127 }; 128 129 void f(B b) { 130 b.f(); 131 } 132 } 133 134 namespace Test6 { 135 struct X { 136 X(); 137 X(const X&); 138 X &operator=(const X&); 139 ~X(); 140 }; 141 142 struct P { 143 P(); 144 P(const P&); 145 ~P(); 146 X first; 147 X second; 148 }; 149 150 P getP(); 151 152 struct Base1 { 153 int i; 154 155 virtual X f() { return X(); } 156 }; 157 158 struct Base2 { 159 float real; 160 161 virtual X f() { return X(); } 162 }; 163 164 struct Thunks : Base1, Base2 { 165 long l; 166 167 virtual X f(); 168 }; 169 170 // CHECK: define void @_ZThn16_N5Test66Thunks1fEv 171 // CHECK-NOT: memcpy 172 // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}} 173 // CHECK: ret void 174 X Thunks::f() { return X(); } 175 } 176 177 namespace Test7 { 178 // PR7188 179 struct X { 180 X(); 181 X(const X&); 182 X &operator=(const X&); 183 ~X(); 184 }; 185 186 struct Small { short s; }; 187 struct Large { 188 char array[1024]; 189 }; 190 191 class A { 192 protected: 193 virtual void foo() = 0; 194 }; 195 196 class B : public A { 197 protected: 198 virtual void bar() = 0; 199 }; 200 201 class C : public A { 202 protected: 203 virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0; 204 }; 205 206 class D : public B, 207 public C { 208 209 void foo() {} 210 void bar() {} 211 void baz(X, X&, _Complex float, Small, Small&, Large); 212 }; 213 214 void D::baz(X, X&, _Complex float, Small, Small&, Large) { } 215 216 // CHECK: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE( 217 // CHECK-NOT: memcpy 218 // CHECK: ret void 219 void testD() { D d; } 220 } 221 222 namespace Test8 { 223 struct NonPOD { ~NonPOD(); int x, y, z; }; 224 struct A { virtual void foo(); }; 225 struct B { virtual void bar(NonPOD); }; 226 struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); }; 227 228 // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]* 229 void C::helper(NonPOD var) {} 230 231 // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE( 232 // CHECK-NOT: load [[NONPODTYPE]]* 233 // CHECK-NOT: memcpy 234 // CHECK: ret void 235 void C::bar(NonPOD var) {} 236 } 237 238 // PR7241: Emitting thunks for a method shouldn't require the vtable for 239 // that class to be emitted. 240 namespace Test9 { 241 struct A { virtual ~A() { } }; 242 struct B : A { virtual void test() const {} }; 243 struct C : B { C(); ~C(); }; 244 struct D : C { D() {} }; 245 void test() { 246 D d; 247 } 248 } 249 250 namespace Test10 { 251 struct A { virtual void foo(); }; 252 struct B { virtual void foo(); }; 253 struct C : A, B { void foo() {} }; 254 255 // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv 256 // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv 257 258 void test() { 259 C c; 260 } 261 } 262 263 // PR7611 264 namespace Test11 { 265 struct A { virtual A* f(); }; 266 struct B : virtual A { virtual A* f(); }; 267 struct C : B { virtual C* f(); }; 268 C* C::f() { return 0; } 269 270 // The this-adjustment and return-adjustment thunk required when 271 // C::f appears in a vtable where A is at a nonzero offset from C. 272 // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv( 273 274 // C::f itself. 275 // CHECK: define {{.*}} @_ZN6Test111C1fEv( 276 277 // The return-adjustment thunk required when C::f appears in a vtable 278 // where A is at a zero offset from C. 279 // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv( 280 } 281 282 /**** The following has to go at the end of the file ****/ 283 284 // This is from Test5: 285 // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv 286 // CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( 287