r217910 - Don't try to devirtualize non-virtual calls

Reid Kleckner reid at kleckner.net
Tue Sep 16 15:23:33 PDT 2014


Author: rnk
Date: Tue Sep 16 17:23:33 2014
New Revision: 217910

URL: http://llvm.org/viewvc/llvm-project?rev=217910&view=rev
Log:
Don't try to devirtualize non-virtual calls

We would end up marking the vtable of the derived class as used for no
reason. Because the call itself is qualified, it is never virtual, and
the vtable of the derived class isn't helpful. We would end up rejecting
code that MSVC accepts for no benefit.

See http://crbug.com/413478

Added:
    cfe/trunk/test/SemaCXX/devirtualize-vtable-marking.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=217910&r1=217909&r2=217910&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Sep 16 17:23:33 2014
@@ -12581,6 +12581,10 @@ static void MarkExprReferenced(Sema &Sem
   CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
   if (!MD)
     return;
+  // Only attempt to devirtualize if this is truly a virtual call.
+  bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+  if (!IsVirtualCall)
+    return;
   const Expr *Base = ME->getBase();
   const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
   if (!MostDerivedClassDecl)

Added: cfe/trunk/test/SemaCXX/devirtualize-vtable-marking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/devirtualize-vtable-marking.cpp?rev=217910&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/devirtualize-vtable-marking.cpp (added)
+++ cfe/trunk/test/SemaCXX/devirtualize-vtable-marking.cpp Tue Sep 16 17:23:33 2014
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+template <typename T> struct OwnPtr {
+  T *p;
+  ~OwnPtr() {
+    // expected-error at +1 {{invalid application of 'sizeof'}}
+    static_assert(sizeof(T) > 0, "incomplete T");
+    delete p;
+  }
+};
+
+namespace use_vtable_for_vcall {
+struct Incomplete; // expected-note {{forward declaration}}
+struct A {
+  virtual ~A() {}
+  virtual void m() {}
+};
+struct B : A { // expected-note {{in instantiation}}
+  B();
+  virtual void m() { }
+  virtual void m2() { static_cast<A *>(this)->m(); }
+  OwnPtr<Incomplete> m_sqlError;
+};
+
+B *f() {
+  return new B();
+}
+}
+
+namespace dont_mark_qualified_vcall {
+struct Incomplete;
+struct A {
+  virtual ~A() {}
+  virtual void m() {}
+};
+struct B : A {
+  B();
+  // Previously we would mark B's vtable referenced to devirtualize this call to
+  // A::m, even though it's not a virtual call.
+  virtual void m() { A::m(); }
+  OwnPtr<Incomplete> m_sqlError;
+};
+
+B *f() {
+  return new B();
+}
+}





More information about the cfe-commits mailing list