198 lines · cpp
1// RUN: %clang_cc1 -std=c++98 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s2// RUN: %clang_cc1 -std=c++11 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s3// RUN: %clang_cc1 -std=c++1z %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s4 5struct A {6 virtual void f();7 virtual void f_const() const;8 virtual void g();9 10 A h();11};12 13A g();14 15void f(A a, A *ap, A& ar) {16 // This should not be a virtual function call.17 18 // CHECK: call void @_ZN1A1fEv(ptr {{[^,]*}} %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 @_ZN1A1fEv28 A().f();29 30 // CHECK: call void @_ZN1A1fEv31 g().f();32 33 // CHECK: call void @_ZN1A1fEv34 a.h().f();35 36 // CHECK: call void @_ZNK1A7f_constEv37 a.f_const();38 39 // CHECK: call void @_ZN1A1fEv40 (a).f();41}42 43struct D : A { virtual void g(); };44struct XD { D d; };45 46D gd();47 48void fd(D d, XD xd, D *p) {49 // CHECK: call void @_ZN1A1fEv(ptr50 d.f();51 52 // CHECK: call void @_ZN1D1gEv(ptr53 d.g();54 55 // CHECK: call void @_ZN1A1fEv56 D().f();57 58 // CHECK: call void @_ZN1D1gEv59 D().g();60 61 // CHECK: call void @_ZN1A1fEv62 gd().f();63 64 // CHECK: call void @_ZNK1A7f_constEv65 d.f_const();66 67 // CHECK: call void @_ZN1A1fEv68 (d).f();69 70 // CHECK: call void @_ZN1A1fEv71 (true, d).f();72 73 // CHECK: call void @_ZN1D1gEv74 (true, d).g();75 76 // CHECK: call void @_ZN1A1fEv77 xd.d.f();78 79 // CHECK: call void @_ZN1A1fEv80 XD().d.f();81 82 // CHECK: call void @_ZN1A1fEv83 D XD::*mp;84 (xd.*mp).f();85 86 // CHECK: call void @_ZN1D1gEv87 (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 array96 // element type and the pointee type are not similar, behavior is undefined).97 // CHECK: call void %98 p[1].f();99}100 101struct B {102 virtual void f();103 ~B();104 105 B h();106};107 108 109void f() {110 // CHECK: call void @_ZN1B1fEv111 B().f();112 113 // CHECK: call void @_ZN1B1fEv114 B().h().f();115}116 117namespace 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 128 void f(bar *b) {129 // CHECK: call void @_ZN5test23foo1fEv130 // CHECK: call noundef ptr @_ZN5test23fooD1Ev131 b->foo::f();132 b->foo::~foo();133 }134}135 136namespace test3 {137 // Test that we don't crash in this case.138 struct B {139 };140 struct D : public B {141 };142 void f(D d) {143 // CHECK-LABEL: define{{.*}} void @_ZN5test31fENS_1DE144 d.B::~B();145 }146}147 148namespace 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;159 void test() {160 // CHECK: call void @_ZN5test44Fish3eatEv161 p->fish.eat();162 }163}164 165// Do not devirtualize to pure virtual function calls.166namespace test5 {167 struct X {168 virtual void f() = 0;169 };170 struct Y {};171 // CHECK-LABEL: define {{.*}} @_ZN5test51f172 void f(Y &y, X Y::*p) {173 // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv174 // CHECK: call void %175 (y.*p).f();176 };177 178 struct Z final {179 virtual void f() = 0;180 };181 // CHECK-LABEL: define {{.*}} @_ZN5test51g182 void g(Z &z) {183 // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv184 // CHECK: call void %185 z.f();186 }187 188 struct Q {189 virtual void f() final = 0;190 };191 // CHECK-LABEL: define {{.*}} @_ZN5test51h192 void h(Q &q) {193 // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv194 // CHECK: call void %195 q.f();196 }197}198