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 | 2246167362bf3596f13988723b363449b8427cfd (patch) | |
tree | 7e0bdc9ff27963518c08aa8b4e1b9d964eae091d /clang/test | |
parent | fa5183b0280fe0d0bc44f1bbc8f24d744013e31b (diff) | |
download | bcm5719-llvm-2246167362bf3596f13988723b363449b8427cfd.tar.gz bcm5719-llvm-2246167362bf3596f13988723b363449b8427cfd.zip |
[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
llvm-svn: 307883
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/no-devirt.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp | 50 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-available-externally.cpp | 5 |
3 files changed, 54 insertions, 5 deletions
diff --git a/clang/test/CodeGen/no-devirt.cpp b/clang/test/CodeGen/no-devirt.cpp index 4333b7cde7c..544b1394f42 100644 --- a/clang/test/CodeGen/no-devirt.cpp +++ b/clang/test/CodeGen/no-devirt.cpp @@ -21,7 +21,7 @@ public: struct Wrapper { TmplWithArray<bool, 10> data; bool indexIt(int a) { - if (a > 6) return data[a] ; // Should not devirtualize + if (a > 6) return data[a] ; // Should devirtualize if (a > 4) return data.func1(a); // Should devirtualize return data.func2(a); // Should devirtualize } @@ -53,7 +53,7 @@ bool stuff(int p) } #endif -// CHECK-NOT: call {{.*}} @_ZN13TmplWithArrayIbLi10EEixEi +// CHECK-DAG: call {{.*}} @_ZN13TmplWithArrayIbLi10EEixEi // CHECK-DAG: call {{.*}} @_ZN13TmplWithArrayIbLi10EE5func1Ei // CHECK-DAG: call {{.*}} @_ZN13TmplWithArrayIbLi10EE5func2Ei diff --git a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp index b90620ab600..2ab2f759cfe 100644 --- a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp +++ b/clang/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/clang/test/CodeGenCXX/vtable-available-externally.cpp b/clang/test/CodeGenCXX/vtable-available-externally.cpp index db99f73d9e7..2e2cdbbfeff 100644 --- a/clang/test/CodeGenCXX/vtable-available-externally.cpp +++ b/clang/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(); }; |