summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2017-07-13 06:08:27 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2017-07-13 06:08:27 +0000
commited14d7adea8dda8882104c6dfac3b3d233fff64d (patch)
tree5d0be874d4abc6d111c20cb8bd16670202901259 /test/CodeGenCXX
parent48dec96ecc02497042ad46c7371383db981b1482 (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.cpp50
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp5
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();
};