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