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