diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2017-07-13 06:08:27 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2017-07-13 06:08:27 +0000 |
commit | ed14d7adea8dda8882104c6dfac3b3d233fff64d (patch) | |
tree | 5d0be874d4abc6d111c20cb8bd16670202901259 /test/CodeGenCXX | |
parent | 48dec96ecc02497042ad46c7371383db981b1482 (diff) |
[Sema] Mark a virtual CXXMethodDecl as used if a call to it can be
devirtualized.
The code to detect devirtualized calls is already in IRGen, so move the
code to lib/AST and make it a shared utility between Sema and IRGen.
This commit fixes a linkage error I was seeing when compiling the
following code:
$ cat test1.cpp
struct Base {
virtual void operator()() {}
};
template<class T>
struct Derived final : Base {
void operator()() override {}
};
Derived<int> *d;
int main() {
if (d)
(*d)();
return 0;
}
rdar://problem/33195657
Differential Revision: https://reviews.llvm.org/D34301
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307883 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r-- | test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp | 50 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-available-externally.cpp | 5 |
2 files changed, 52 insertions, 3 deletions
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp index b90620ab60..2ab2f759cf 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp @@ -241,3 +241,53 @@ namespace Test10 { return static_cast<A *>(b)->f(); } } + +namespace Test11 { + // Check that the definitions of Derived's operators are emitted. + + // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev( + // CHECK: call void @_ZN6Test111SIiE7DerivedclEv( + // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( + // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedntEv( + // CHECK: call dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi( + // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv( + // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE( + // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedntEv( + // CHECK: define linkonce_odr dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi( + class Base { + public: + virtual void operator()() {} + virtual bool operator==(const Base &other) { return false; } + virtual bool operator!() { return false; } + virtual Base &operator[](int i) { return *this; } + }; + + template<class T> + struct S { + class Derived final : public Base { + public: + void operator()() override {} + bool operator==(const Base &other) override { return true; } + bool operator!() override { return true; } + Base &operator[](int i) override { return *this; } + }; + + Derived *ptr = nullptr, *ptr2 = nullptr; + + void foo1() { + if (ptr && ptr2) { + // These calls get devirtualized. Linkage fails if the definitions of + // the called functions are not emitted. + (*ptr)(); + (void)(*ptr == *ptr2); + (void)(!(*ptr)); + (void)((*ptr)[1]); + } + } + }; + + void foo2() { + S<int> *s = new S<int>; + s->foo1(); + } +} diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index db99f73d9e..2e2cdbbfef 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -275,9 +275,8 @@ struct C { virtual D& operator=(const D&); }; -// Cannot emit D's vtable available_externally, because we cannot create -// a reference to the inline virtual D::operator= function. -// CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant +// Can emit D's vtable available_externally. +// CHECK-TEST11: @_ZTVN6Test111DE = available_externally unnamed_addr constant struct D : C { virtual void key(); }; |