1 // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s 2 3 namespace Test1 { 4 struct A { 5 virtual int f() final; 6 }; 7 8 // CHECK-LABEL: define i32 @_ZN5Test11fEPNS_1AE f(A * a)9 int f(A *a) { 10 // CHECK: call i32 @_ZN5Test11A1fEv 11 return a->f(); 12 } 13 } 14 15 namespace Test2 { 16 struct A final { 17 virtual int f(); 18 }; 19 20 // CHECK-LABEL: define i32 @_ZN5Test21fEPNS_1AE f(A * a)21 int f(A *a) { 22 // CHECK: call i32 @_ZN5Test21A1fEv 23 return a->f(); 24 } 25 } 26 27 namespace Test3 { 28 struct A { 29 virtual int f(); 30 }; 31 32 struct B final : A { }; 33 34 // CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE f(B * b)35 int f(B *b) { 36 // CHECK: call i32 @_ZN5Test31A1fEv 37 return b->f(); 38 } 39 40 // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE f(B & b)41 int f(B &b) { 42 // CHECK: call i32 @_ZN5Test31A1fEv 43 return b.f(); 44 } 45 46 // CHECK-LABEL: define i32 @_ZN5Test31fEPv f(void * v)47 int f(void *v) { 48 // CHECK: call i32 @_ZN5Test31A1fEv 49 return static_cast<B*>(v)->f(); 50 } 51 } 52 53 namespace Test4 { 54 struct A { 55 virtual void f(); 56 virtual int operator-(); 57 }; 58 59 struct B final : A { 60 virtual void f(); 61 virtual int operator-(); 62 }; 63 64 // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE f(B * d)65 void f(B* d) { 66 // CHECK: call void @_ZN5Test41B1fEv 67 static_cast<A*>(d)->f(); 68 // CHECK: call i32 @_ZN5Test41BngEv 69 -static_cast<A&>(*d); 70 } 71 } 72 73 namespace Test5 { 74 struct A { 75 virtual void f(); 76 virtual int operator-(); 77 }; 78 79 struct B : A { 80 virtual void f(); 81 virtual int operator-(); 82 }; 83 84 struct C final : B { 85 }; 86 87 // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE f(C * d)88 void f(C* d) { 89 // FIXME: It should be possible to devirtualize this case, but that is 90 // not implemented yet. 91 // CHECK: getelementptr 92 // CHECK-NEXT: %[[FUNC:.*]] = load 93 // CHECK-NEXT: call void %[[FUNC]] 94 static_cast<A*>(d)->f(); 95 } 96 // CHECK-LABEL: define void @_ZN5Test53fopEPNS_1CE fop(C * d)97 void fop(C* d) { 98 // FIXME: It should be possible to devirtualize this case, but that is 99 // not implemented yet. 100 // CHECK: getelementptr 101 // CHECK-NEXT: %[[FUNC:.*]] = load 102 // CHECK-NEXT: call i32 %[[FUNC]] 103 -static_cast<A&>(*d); 104 } 105 } 106 107 namespace Test6 { 108 struct A { 109 virtual ~A(); 110 }; 111 112 struct B : public A { 113 virtual ~B(); 114 }; 115 116 struct C { 117 virtual ~C(); 118 }; 119 120 struct D final : public C, public B { 121 }; 122 123 // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE f(D * d)124 void f(D* d) { 125 // CHECK: call void @_ZN5Test61DD1Ev 126 static_cast<A*>(d)->~A(); 127 } 128 } 129 130 namespace Test7 { 131 struct foo { gTest7::foo132 virtual void g() {} 133 }; 134 135 struct bar { fTest7::bar136 virtual int f() { return 0; } 137 }; 138 139 struct zed final : public foo, public bar { 140 int z; fTest7::zed141 virtual int f() {return z;} 142 }; 143 144 // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE f(zed * z)145 int f(zed *z) { 146 // CHECK: alloca 147 // CHECK-NEXT: store 148 // CHECK-NEXT: load 149 // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv 150 // CHECK-NEXT: ret 151 return static_cast<bar*>(z)->f(); 152 } 153 } 154 155 namespace Test8 { ~ATest8::A156 struct A { virtual ~A() {} }; 157 struct B { 158 int b; fooTest8::B159 virtual int foo() { return b; } 160 }; 161 struct C final : A, B { }; 162 // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE test(C * c)163 int test(C *c) { 164 // CHECK: %[[THIS:.*]] = phi 165 // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]]) 166 return static_cast<B*>(c)->foo(); 167 } 168 } 169 170 namespace Test9 { 171 struct A { 172 int a; 173 }; 174 struct B { 175 int b; 176 }; 177 struct C : public B, public A { 178 }; 179 struct RA { fTest9::RA180 virtual A *f() { 181 return 0; 182 } operator -Test9::RA183 virtual A *operator-() { 184 return 0; 185 } 186 }; 187 struct RC final : public RA { fTest9::RC188 virtual C *f() { 189 C *x = new C(); 190 x->a = 1; 191 x->b = 2; 192 return x; 193 } operator -Test9::RC194 virtual C *operator-() { 195 C *x = new C(); 196 x->a = 1; 197 x->b = 2; 198 return x; 199 } 200 }; 201 // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE f(RC * x)202 A *f(RC *x) { 203 // FIXME: It should be possible to devirtualize this case, but that is 204 // not implemented yet. 205 // CHECK: load 206 // CHECK: bitcast 207 // CHECK: [[F_PTR_RA:%.+]] = bitcast 208 // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] 209 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0 210 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 211 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 212 return static_cast<RA*>(x)->f(); 213 } 214 // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE fop(RC * x)215 A *fop(RC *x) { 216 // FIXME: It should be possible to devirtualize this case, but that is 217 // not implemented yet. 218 // CHECK: load 219 // CHECK: bitcast 220 // CHECK: [[F_PTR_RA:%.+]] = bitcast 221 // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] 222 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1 223 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] 224 // CHECK-NEXT: = call {{.*}} %[[FUNC]] 225 return -static_cast<RA&>(*x); 226 } 227 } 228