1 // RUN: %clang_cc1 -std=c++98 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 -std=c++11 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
3 // RUN: %clang_cc1 -std=c++1z %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
4
5 struct A {
6 virtual void f();
7 virtual void f_const() const;
8 virtual void g();
9
10 A h();
11 };
12
13 A g();
14
f(A a,A * ap,A & ar)15 void f(A a, A *ap, A& ar) {
16 // This should not be a virtual function call.
17
18 // CHECK: call void @_ZN1A1fEv(%struct.A* {{[^,]*}} %a)
19 a.f();
20
21 // CHECK: call void %
22 ap->f();
23
24 // CHECK: call void %
25 ar.f();
26
27 // CHECK: call void @_ZN1A1fEv
28 A().f();
29
30 // CHECK: call void @_ZN1A1fEv
31 g().f();
32
33 // CHECK: call void @_ZN1A1fEv
34 a.h().f();
35
36 // CHECK: call void @_ZNK1A7f_constEv
37 a.f_const();
38
39 // CHECK: call void @_ZN1A1fEv
40 (a).f();
41 }
42
43 struct D : A { virtual void g(); };
44 struct XD { D d; };
45
46 D gd();
47
fd(D d,XD xd,D * p)48 void fd(D d, XD xd, D *p) {
49 // CHECK: call void @_ZN1A1fEv(%struct.A*
50 d.f();
51
52 // CHECK: call void @_ZN1D1gEv(%struct.D*
53 d.g();
54
55 // CHECK: call void @_ZN1A1fEv
56 D().f();
57
58 // CHECK: call void @_ZN1D1gEv
59 D().g();
60
61 // CHECK: call void @_ZN1A1fEv
62 gd().f();
63
64 // CHECK: call void @_ZNK1A7f_constEv
65 d.f_const();
66
67 // CHECK: call void @_ZN1A1fEv
68 (d).f();
69
70 // CHECK: call void @_ZN1A1fEv
71 (true, d).f();
72
73 // CHECK: call void @_ZN1D1gEv
74 (true, d).g();
75
76 // CHECK: call void @_ZN1A1fEv
77 xd.d.f();
78
79 // CHECK: call void @_ZN1A1fEv
80 XD().d.f();
81
82 // CHECK: call void @_ZN1A1fEv
83 D XD::*mp;
84 (xd.*mp).f();
85
86 // CHECK: call void @_ZN1D1gEv
87 (xd.*mp).g();
88
89 // Can't devirtualize this; we have no guarantee that p points to a D here,
90 // due to the "single object is considered to be an array of one element"
91 // rule.
92 // CHECK: call void %
93 p[0].f();
94
95 // FIXME: We can devirtualize this, by C++1z [expr.add]/6 (if the array
96 // element type and the pointee type are not similar, behavior is undefined).
97 // CHECK: call void %
98 p[1].f();
99 }
100
101 struct B {
102 virtual void f();
103 ~B();
104
105 B h();
106 };
107
108
f()109 void f() {
110 // CHECK: call void @_ZN1B1fEv
111 B().f();
112
113 // CHECK: call void @_ZN1B1fEv
114 B().h().f();
115 }
116
117 namespace test2 {
118 struct foo {
119 virtual void f();
120 virtual ~foo();
121 };
122
123 struct bar : public foo {
124 virtual void f();
125 virtual ~bar();
126 };
127
f(bar * b)128 void f(bar *b) {
129 // CHECK: call void @_ZN5test23foo1fEv
130 // CHECK: call %"struct.test2::foo"* @_ZN5test23fooD1Ev
131 b->foo::f();
132 b->foo::~foo();
133 }
134 }
135
136 namespace test3 {
137 // Test that we don't crash in this case.
138 struct B {
139 };
140 struct D : public B {
141 };
f(D d)142 void f(D d) {
143 // CHECK-LABEL: define{{.*}} void @_ZN5test31fENS_1DE
144 d.B::~B();
145 }
146 }
147
148 namespace test4 {
149 struct Animal {
150 virtual void eat();
151 };
152 struct Fish : Animal {
153 virtual void eat();
154 };
155 struct Wrapper {
156 Fish fish;
157 };
158 extern Wrapper *p;
test()159 void test() {
160 // CHECK: call void @_ZN5test44Fish3eatEv
161 p->fish.eat();
162 }
163 }
164
165 // Do not devirtualize to pure virtual function calls.
166 namespace test5 {
167 struct X {
168 virtual void f() = 0;
169 };
170 struct Y {};
171 // CHECK-LABEL: define {{.*}} @_ZN5test51f
f(Y & y,X Y::* p)172 void f(Y &y, X Y::*p) {
173 // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv
174 // CHECK: call void %
175 (y.*p).f();
176 };
177
178 struct Z final {
179 virtual void f() = 0;
180 };
181 // CHECK-LABEL: define {{.*}} @_ZN5test51g
g(Z & z)182 void g(Z &z) {
183 // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv
184 // CHECK: call void %
185 z.f();
186 }
187
188 struct Q {
189 virtual void f() final = 0;
190 };
191 // CHECK-LABEL: define {{.*}} @_ZN5test51h
h(Q & q)192 void h(Q &q) {
193 // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv
194 // CHECK: call void %
195 q.f();
196 }
197 }
198