[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / CodeGenCXX / devirtualize-virtual-function-calls-final.cpp
blob5b1b5a8bb3985dca6baf2e2f9c335ef1909dea6d
1 // RUN: %clang_cc1 -no-opaque-pointers -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
3 namespace Test1 {
4 struct A {
5 virtual int f() final;
6 };
8 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test11fEPNS_1AE
9 int f(A *a) {
10 // CHECK: call noundef i32 @_ZN5Test11A1fEv
11 return a->f();
15 namespace Test2 {
16 struct A final {
17 virtual int f();
20 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test21fEPNS_1AE
21 int f(A *a) {
22 // CHECK: call noundef i32 @_ZN5Test21A1fEv
23 return a->f();
27 namespace Test2a {
28 struct A {
29 virtual ~A() final {}
30 virtual int f();
33 // CHECK-LABEL: define{{.*}} i32 @_ZN6Test2a1fEPNS_1AE
34 int f(A *a) {
35 // CHECK: call noundef i32 @_ZN6Test2a1A1fEv
36 return a->f();
41 namespace Test3 {
42 struct A {
43 virtual int f(); };
45 struct B final : A { };
47 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fEPNS_1BE
48 int f(B *b) {
49 // CHECK: call noundef i32 @_ZN5Test31A1fEv
50 return b->f();
53 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fERNS_1BE
54 int f(B &b) {
55 // CHECK: call noundef i32 @_ZN5Test31A1fEv
56 return b.f();
59 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test31fEPv
60 int f(void *v) {
61 // CHECK: call noundef i32 @_ZN5Test31A1fEv
62 return static_cast<B*>(v)->f();
66 namespace Test4 {
67 struct A {
68 virtual void f();
69 virtual int operator-();
72 struct B final : A {
73 virtual void f();
74 virtual int operator-();
77 // CHECK-LABEL: define{{.*}} void @_ZN5Test41fEPNS_1BE
78 void f(B* d) {
79 // CHECK: call void @_ZN5Test41B1fEv
80 static_cast<A*>(d)->f();
81 // CHECK: call noundef i32 @_ZN5Test41BngEv
82 -static_cast<A&>(*d);
86 namespace Test5 {
87 struct A {
88 virtual void f();
89 virtual int operator-();
92 struct B : A {
93 virtual void f();
94 virtual int operator-();
97 struct C final : B {
100 // CHECK-LABEL: define{{.*}} void @_ZN5Test51fEPNS_1CE
101 void f(C* d) {
102 // FIXME: It should be possible to devirtualize this case, but that is
103 // not implemented yet.
104 // CHECK: getelementptr
105 // CHECK-NEXT: %[[FUNC:.*]] = load
106 // CHECK-NEXT: call void %[[FUNC]]
107 static_cast<A*>(d)->f();
109 // CHECK-LABEL: define{{.*}} void @_ZN5Test53fopEPNS_1CE
110 void fop(C* d) {
111 // FIXME: It should be possible to devirtualize this case, but that is
112 // not implemented yet.
113 // CHECK: getelementptr
114 // CHECK-NEXT: %[[FUNC:.*]] = load
115 // CHECK-NEXT: call noundef i32 %[[FUNC]]
116 -static_cast<A&>(*d);
120 namespace Test6 {
121 struct A {
122 virtual ~A();
125 struct B : public A {
126 virtual ~B();
129 struct C {
130 virtual ~C();
133 struct D final : public C, public B {
136 // CHECK-LABEL: define{{.*}} void @_ZN5Test61fEPNS_1DE
137 void f(D* d) {
138 // CHECK: call void @_ZN5Test61DD1Ev
139 static_cast<A*>(d)->~A();
143 namespace Test7 {
144 struct foo {
145 virtual void g() {}
148 struct bar {
149 virtual int f() { return 0; }
152 struct zed final : public foo, public bar {
153 int z;
154 virtual int f() {return z;}
157 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test71fEPNS_3zedE
158 int f(zed *z) {
159 // CHECK: alloca
160 // CHECK-NEXT: store
161 // CHECK-NEXT: load
162 // CHECK-NEXT: call noundef i32 @_ZN5Test73zed1fEv
163 // CHECK-NEXT: ret
164 return static_cast<bar*>(z)->f();
168 namespace Test8 {
169 struct A { virtual ~A() {} };
170 struct B {
171 int b;
172 virtual int foo() { return b; }
174 struct C final : A, B { };
175 // CHECK-LABEL: define{{.*}} i32 @_ZN5Test84testEPNS_1CE
176 int test(C *c) {
177 // CHECK: %[[THIS:.*]] = phi
178 // CHECK-NEXT: call noundef i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* {{[^,]*}} %[[THIS]])
179 return static_cast<B*>(c)->foo();
183 namespace Test9 {
184 struct A {
185 int a;
187 struct B {
188 int b;
190 struct C : public B, public A {
192 struct RA {
193 virtual A *f() {
194 return 0;
196 virtual A *operator-() {
197 return 0;
200 struct RC final : public RA {
201 virtual C *f() {
202 C *x = new C();
203 x->a = 1;
204 x->b = 2;
205 return x;
207 virtual C *operator-() {
208 C *x = new C();
209 x->a = 1;
210 x->b = 2;
211 return x;
214 // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
215 A *f(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]+}} 0
223 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
224 // CHECK-NEXT: = call {{.*}} %[[FUNC]]
225 return static_cast<RA*>(x)->f();
227 // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE
228 A *fop(RC *x) {
229 // FIXME: It should be possible to devirtualize this case, but that is
230 // not implemented yet.
231 // CHECK: load
232 // CHECK: bitcast
233 // CHECK: [[F_PTR_RA:%.+]] = bitcast
234 // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
235 // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1
236 // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
237 // CHECK-NEXT: = call {{.*}} %[[FUNC]]
238 return -static_cast<RA&>(*x);
242 namespace Test10 {
243 struct A {
244 virtual int f();
247 struct B : A {
248 int f() final;
251 // CHECK-LABEL: define{{.*}} i32 @_ZN6Test101fEPNS_1BE
252 int f(B *b) {
253 // CHECK: call noundef i32 @_ZN6Test101B1fEv
254 return static_cast<A *>(b)->f();
258 namespace TestVBase {
259 struct A { virtual void f(); };
260 struct B : virtual A {};
261 struct C : virtual A { void f() override; };
263 extern struct BC final : B, C {} &bc;
264 extern struct BCusingA final : B, C { using A::f; } &bc_using_a;
265 extern struct BCusingB final : B, C { using B::f; } &bc_using_b;
266 extern struct BCusingC final : B, C { using C::f; } &bc_using_c;
268 extern struct CB final : C, B {} &cb;
269 extern struct CBusingA final : C, B { using A::f; } &cb_using_a;
270 extern struct CBusingB final : C, B { using B::f; } &cb_using_b;
271 extern struct CBusingC final : C, B { using C::f; } &cb_using_c;
273 // CHECK-LABEL: @_ZN9TestVBase4testEv(
274 void test() {
275 // FIXME: The 'using A' case can be devirtualized to call A's virtual
276 // adjustment thunk for C::f.
277 // FIXME: The 'using B' case can be devirtualized, but requires us to emit
278 // a derived-to-base or base-to-derived conversion as part of
279 // devirtualization.
281 // CHECK: call void @_ZN9TestVBase1C1fEv(
282 bc.f();
283 // CHECK: call void %
284 bc_using_a.f();
285 // CHECK: call void %
286 bc_using_b.f();
287 // CHECK: call void @_ZN9TestVBase1C1fEv(
288 bc_using_c.f();
290 // CHECK: call void @_ZN9TestVBase1C1fEv(
291 cb.f();
292 // CHECK: call void %
293 cb_using_a.f();
294 // CHECK: call void %
295 cb_using_b.f();
296 // CHECK: call void @_ZN9TestVBase1C1fEv(
297 cb_using_c.f();
301 namespace Test11 {
302 // Check that the definitions of Derived's operators are emitted.
304 // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev(
305 // CHECK: call void @_ZN6Test111SIiE7DerivedclEv(
306 // CHECK: call noundef zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE(
307 // CHECK: call noundef zeroext i1 @_ZN6Test111SIiE7DerivedntEv(
308 // CHECK: call noundef nonnull align 4 dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi(
309 // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv(
310 // CHECK: define linkonce_odr noundef zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE(
311 // CHECK: define linkonce_odr noundef zeroext i1 @_ZN6Test111SIiE7DerivedntEv(
312 // CHECK: define linkonce_odr noundef nonnull align 4 dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi(
313 class Base {
314 public:
315 virtual void operator()() {}
316 virtual bool operator==(const Base &other) { return false; }
317 virtual bool operator!() { return false; }
318 virtual Base &operator[](int i) { return *this; }
321 template<class T>
322 struct S {
323 class Derived final : public Base {
324 public:
325 void operator()() override {}
326 bool operator==(const Base &other) override { return true; }
327 bool operator!() override { return true; }
328 Base &operator[](int i) override { return *this; }
331 Derived *ptr = nullptr, *ptr2 = nullptr;
333 void foo1() {
334 if (ptr && ptr2) {
335 // These calls get devirtualized. Linkage fails if the definitions of
336 // the called functions are not emitted.
337 (*ptr)();
338 (void)(*ptr == *ptr2);
339 (void)(!(*ptr));
340 (void)((*ptr)[1]);
345 void foo2() {
346 S<int> *s = new S<int>;
347 s->foo1();