[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