xref: /llvm-project/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp (revision 4362261b0093730e46ffcad910e8b465cf0bb1cb)
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
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
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
35   int f(B *b) {
36     // CHECK: call i32 @_ZN5Test31A1fEv
37     return b->f();
38   }
39 
40   // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE
41   int f(B &b) {
42     // CHECK: call i32 @_ZN5Test31A1fEv
43     return b.f();
44   }
45 
46   // CHECK-LABEL: define i32 @_ZN5Test31fEPv
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   };
57 
58   struct B final : A {
59     virtual void f();
60   };
61 
62   // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE
63   void f(B* d) {
64     // CHECK: call void @_ZN5Test41B1fEv
65     static_cast<A*>(d)->f();
66   }
67 }
68 
69 namespace Test5 {
70   struct A {
71     virtual void f();
72   };
73 
74   struct B : A {
75     virtual void f();
76   };
77 
78   struct C final : B {
79   };
80 
81   // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE
82   void f(C* d) {
83     // FIXME: It should be possible to devirtualize this case, but that is
84     // not implemented yet.
85     // CHECK: getelementptr
86     // CHECK-NEXT: %[[FUNC:.*]] = load
87     // CHECK-NEXT: call void %[[FUNC]]
88     static_cast<A*>(d)->f();
89   }
90 }
91 
92 namespace Test6 {
93   struct A {
94     virtual ~A();
95   };
96 
97   struct B : public A {
98     virtual ~B();
99   };
100 
101   struct C {
102     virtual ~C();
103   };
104 
105   struct D final : public C, public B {
106   };
107 
108   // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE
109   void f(D* d) {
110     // CHECK: call void @_ZN5Test61DD1Ev
111     static_cast<A*>(d)->~A();
112   }
113 }
114 
115 namespace Test7 {
116   struct foo {
117     virtual void g() {}
118   };
119 
120   struct bar {
121     virtual int f() { return 0; }
122   };
123 
124   struct zed final : public foo, public bar {
125     int z;
126     virtual int f() {return z;}
127   };
128 
129   // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
130   int f(zed *z) {
131     // CHECK: alloca
132     // CHECK-NEXT: store
133     // CHECK-NEXT: load
134     // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv
135     // CHECK-NEXT: ret
136     return static_cast<bar*>(z)->f();
137   }
138 }
139 
140 namespace Test8 {
141   struct A { virtual ~A() {} };
142   struct B {
143     int b;
144     virtual int foo() { return b; }
145   };
146   struct C final : A, B {  };
147   // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
148   int test(C *c) {
149     // CHECK: %[[THIS:.*]] = phi
150     // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
151     return static_cast<B*>(c)->foo();
152   }
153 }
154 
155 namespace Test9 {
156   struct A {
157     int a;
158   };
159   struct B {
160     int b;
161   };
162   struct C : public B, public A {
163   };
164   struct RA {
165     virtual A *f() {
166       return 0;
167     }
168   };
169   struct RC final : public RA {
170     virtual C *f() {
171       C *x = new C();
172       x->a = 1;
173       x->b = 2;
174       return x;
175     }
176   };
177   // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
178   A *f(RC *x) {
179     // FIXME: It should be possible to devirtualize this case, but that is
180     // not implemented yet.
181     // CHECK: getelementptr
182     // CHECK-NEXT: %[[FUNC:.*]] = load
183     // CHECK-NEXT: bitcast
184     // CHECK-NEXT: = call {{.*}} %[[FUNC]]
185     return static_cast<RA*>(x)->f();
186   }
187 }
188