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