[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