[PATCH] D34301: [Sema] Make sure the definition of a referenced virtual function is emitted when it is final
Akira Hatanaka via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 16 16:22:37 PDT 2017
ahatanak created this revision.
Herald added a subscriber: Prazek.
The test case I added used to fail because of a linker error.
Linkage failed because Sema::MarkDeclRefReferenced would prevent the virtual method definition from being emitted by setting OdrUse=false and then code-gen would devirtualized the virtual call because its class is marked final.
This patch fixes the bug.
rdar://problem/27455779
https://reviews.llvm.org/D34301
Files:
lib/Sema/SemaExpr.cpp
test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
Index: test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
===================================================================
--- test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -241,3 +241,40 @@
return static_cast<A *>(b)->f();
}
}
+
+namespace Test11 {
+ // Check that the definition of Derived::operator() is emitted.
+
+ // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev(
+ // CHECK: call void @_ZN6Test111SIiE7DerivedclEv(
+ // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv(
+ class Base {
+ public:
+ virtual void operator()() {
+ }
+ };
+
+ template<class T>
+ struct S {
+ class Derived final : public Base {
+ public:
+ void operator()() override {
+ }
+ };
+
+ Derived *ptr = nullptr;
+
+ void foo1() {
+ if (ptr) {
+ // This call gets devirtualized. If the definition of
+ // Derived::operator() is not emitted, there will be a linker error.
+ (*ptr)();
+ }
+ }
+ };
+
+ void foo2() {
+ S<int> *s = new S<int>;
+ s->foo1();
+ }
+}
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -14711,7 +14711,8 @@
// if it's a qualified reference.
bool OdrUse = true;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl()))
- if (Method->isVirtual())
+ if (Method->isVirtual() && !(Method->hasAttr<FinalAttr>() ||
+ Method->getParent()->hasAttr<FinalAttr>()))
OdrUse = false;
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D34301.102897.patch
Type: text/x-patch
Size: 1734 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170616/c46cd9ca/attachment.bin>
More information about the cfe-commits
mailing list