diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
| commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
| tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /test/CodeGenCXX/devirtualize-virtual-function-calls.cpp | |
| parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) | |
Notes
Diffstat (limited to 'test/CodeGenCXX/devirtualize-virtual-function-calls.cpp')
| -rw-r--r-- | test/CodeGenCXX/devirtualize-virtual-function-calls.cpp | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp index 911ddeedd236..b4c39f3fcff5 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp @@ -1,8 +1,11 @@ -// RUN: %clang_cc1 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++1z %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s struct A { virtual void f(); virtual void f_const() const; + virtual void g(); A h(); }; @@ -37,6 +40,64 @@ void f(A a, A *ap, A& ar) { (a).f(); } +struct D : A { virtual void g(); }; +struct XD { D d; }; + +D gd(); + +void fd(D d, XD xd, D *p) { + // CHECK: call void @_ZN1A1fEv(%struct.A* + d.f(); + + // CHECK: call void @_ZN1D1gEv(%struct.D* + d.g(); + + // CHECK: call void @_ZN1A1fEv + D().f(); + + // CHECK: call void @_ZN1D1gEv + D().g(); + + // CHECK: call void @_ZN1A1fEv + gd().f(); + + // CHECK: call void @_ZNK1A7f_constEv + d.f_const(); + + // CHECK: call void @_ZN1A1fEv + (d).f(); + + // CHECK: call void @_ZN1A1fEv + (true, d).f(); + + // CHECK: call void @_ZN1D1gEv + (true, d).g(); + + // CHECK: call void @_ZN1A1fEv + xd.d.f(); + + // CHECK: call void @_ZN1A1fEv + XD().d.f(); + + // CHECK: call void @_ZN1A1fEv + D XD::*mp; + (xd.*mp).f(); + + // CHECK: call void @_ZN1D1gEv + (xd.*mp).g(); + + // Can't devirtualize this; we have no guarantee that p points to a D here, + // due to the "single object is considered to be an array of one element" + // rule. + // CHECK: call void % + p[0].f(); + + // FIXME: We can devirtualize this, by C++1z [expr.add]/6 (if the array + // element type and the pointee type are not similar, behavior is undefined). + // CHECK: call void % + p[1].f(); +} + struct B { virtual void f(); ~B(); @@ -100,3 +161,37 @@ namespace test4 { p->fish.eat(); } } + +// Do not devirtualize to pure virtual function calls. +namespace test5 { + struct X { + virtual void f() = 0; + }; + struct Y {}; + // CHECK-LABEL: define {{.*}} @_ZN5test51f + void f(Y &y, X Y::*p) { + // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv + // CHECK: call void % + (y.*p).f(); + }; + + struct Z final { + virtual void f() = 0; + }; + // CHECK-LABEL: define {{.*}} @_ZN5test51g + void g(Z &z) { + // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv + // CHECK: call void % + z.f(); + } + + struct Q { + virtual void f() final = 0; + }; + // CHECK-LABEL: define {{.*}} @_ZN5test51h + void h(Q &q) { + // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv + // CHECK: call void % + q.f(); + } +} |
