[cfe-commits] r124524 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp

Anders Carlsson andersca at mac.com
Fri Jan 28 19:52:02 PST 2011


Author: andersca
Date: Fri Jan 28 21:52:01 2011
New Revision: 124524

URL: http://llvm.org/viewvc/llvm-project?rev=124524&view=rev
Log:
When calling a virtual member function on a base class and the most derived class is marked 'final', we can devirtualize the call.

Modified:
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=124524&r1=124523&r2=124524&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Jan 28 21:52:01 2011
@@ -53,16 +53,39 @@
                   Callee, ReturnValue, Args, MD);
 }
 
+static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) {
+  QualType DerivedType = Base->IgnoreParenCasts()->getType();
+  if (const PointerType *PTy = DerivedType->getAs<PointerType>())
+    DerivedType = PTy->getPointeeType();
+
+  return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl());
+}
+
 /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
 /// expr can be devirtualized.
 static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
                                                const Expr *Base, 
                                                const CXXMethodDecl *MD) {
   
-  // Cannot divirtualize in kext mode.
+  // When building with -fapple-kext, all calls must go through the vtable since
+  // the kernel linker can do runtime patching of vtables.
   if (Context.getLangOptions().AppleKext)
     return false;
 
+  // If the most derived class is marked final, we know that no subclass can
+  // override this member function and so we can devirtualize it. For example:
+  //
+  // struct A { virtual void f(); }
+  // struct B final : A { };
+  //
+  // void f(B *b) {
+  //   b->f();
+  // }
+  //
+  const CXXRecordDecl *MostDerivedClassDecl = getMostDerivedClassDecl(Base);
+  if (MostDerivedClassDecl->hasAttr<FinalAttr>())
+    return true;
+
   // If the member function is marked 'final', we know that it can't be
   // overridden and can therefore devirtualize it.
   if (MD->hasAttr<FinalAttr>())

Modified: cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp?rev=124524&r1=124523&r2=124524&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp Fri Jan 28 21:52:01 2011
@@ -23,3 +23,17 @@
     return a->f();
   }
 }
+
+namespace Test3 {
+  struct A {
+    virtual int f();
+  };
+
+  struct B final : A { };
+
+  // CHECK: define i32 @_ZN5Test31fEPNS_1BE
+  int f(B *b) {
+    // CHECK: call i32 @_ZN5Test31A1fEv
+    return b->f();
+  }
+}





More information about the cfe-commits mailing list