[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / CodeGenCXX / devirtualize-virtual-function-calls.cpp
blobb50881db63e055ebc80a49bc1ea173386986ecb1
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
5 struct A {
6 virtual void f();
7 virtual void f_const() const;
8 virtual void g();
10 A h();
13 A g();
15 void f(A a, A *ap, A& ar) {
16 // This should not be a virtual function call.
18 // CHECK: call void @_ZN1A1fEv(ptr {{[^,]*}} %a)
19 a.f();
21 // CHECK: call void %
22 ap->f();
24 // CHECK: call void %
25 ar.f();
27 // CHECK: call void @_ZN1A1fEv
28 A().f();
30 // CHECK: call void @_ZN1A1fEv
31 g().f();
33 // CHECK: call void @_ZN1A1fEv
34 a.h().f();
36 // CHECK: call void @_ZNK1A7f_constEv
37 a.f_const();
39 // CHECK: call void @_ZN1A1fEv
40 (a).f();
43 struct D : A { virtual void g(); };
44 struct XD { D d; };
46 D gd();
48 void fd(D d, XD xd, D *p) {
49 // CHECK: call void @_ZN1A1fEv(ptr
50 d.f();
52 // CHECK: call void @_ZN1D1gEv(ptr
53 d.g();
55 // CHECK: call void @_ZN1A1fEv
56 D().f();
58 // CHECK: call void @_ZN1D1gEv
59 D().g();
61 // CHECK: call void @_ZN1A1fEv
62 gd().f();
64 // CHECK: call void @_ZNK1A7f_constEv
65 d.f_const();
67 // CHECK: call void @_ZN1A1fEv
68 (d).f();
70 // CHECK: call void @_ZN1A1fEv
71 (true, d).f();
73 // CHECK: call void @_ZN1D1gEv
74 (true, d).g();
76 // CHECK: call void @_ZN1A1fEv
77 xd.d.f();
79 // CHECK: call void @_ZN1A1fEv
80 XD().d.f();
82 // CHECK: call void @_ZN1A1fEv
83 D XD::*mp;
84 (xd.*mp).f();
86 // CHECK: call void @_ZN1D1gEv
87 (xd.*mp).g();
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();
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();
101 struct B {
102 virtual void f();
103 ~B();
105 B h();
109 void f() {
110 // CHECK: call void @_ZN1B1fEv
111 B().f();
113 // CHECK: call void @_ZN1B1fEv
114 B().h().f();
117 namespace test2 {
118 struct foo {
119 virtual void f();
120 virtual ~foo();
123 struct bar : public foo {
124 virtual void f();
125 virtual ~bar();
128 void f(bar *b) {
129 // CHECK: call void @_ZN5test23foo1fEv
130 // CHECK: call noundef ptr @_ZN5test23fooD1Ev
131 b->foo::f();
132 b->foo::~foo();
136 namespace test3 {
137 // Test that we don't crash in this case.
138 struct B {
140 struct D : public B {
142 void f(D d) {
143 // CHECK-LABEL: define{{.*}} void @_ZN5test31fENS_1DE
144 d.B::~B();
148 namespace test4 {
149 struct Animal {
150 virtual void eat();
152 struct Fish : Animal {
153 virtual void eat();
155 struct Wrapper {
156 Fish fish;
158 extern Wrapper *p;
159 void test() {
160 // CHECK: call void @_ZN5test44Fish3eatEv
161 p->fish.eat();
165 // Do not devirtualize to pure virtual function calls.
166 namespace test5 {
167 struct X {
168 virtual void f() = 0;
170 struct Y {};
171 // CHECK-LABEL: define {{.*}} @_ZN5test51f
172 void f(Y &y, X Y::*p) {
173 // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv
174 // CHECK: call void %
175 (y.*p).f();
178 struct Z final {
179 virtual void f() = 0;
181 // CHECK-LABEL: define {{.*}} @_ZN5test51g
182 void g(Z &z) {
183 // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv
184 // CHECK: call void %
185 z.f();
188 struct Q {
189 virtual void f() final = 0;
191 // CHECK-LABEL: define {{.*}} @_ZN5test51h
192 void h(Q &q) {
193 // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv
194 // CHECK: call void %
195 q.f();