summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprCXX.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2011-01-29 03:52:01 +0000
committerAnders Carlsson <andersca@mac.com>2011-01-29 03:52:01 +0000
commit1679f5a84ae1e578b0de347c89eaf31e0465f33c (patch)
tree63f9aeb69eaefebba9deaaf42f54816f19f69de2 /lib/CodeGen/CGExprCXX.cpp
parent336a7dc56871ccfeceecc296c9624f66f7ac01ec (diff)
downloadclang-1679f5a84ae1e578b0de347c89eaf31e0465f33c.tar.gz
When calling a virtual member function on a base class and the most derived class is marked 'final', we can devirtualize the call.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124524 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r--lib/CodeGen/CGExprCXX.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 03b90e2587..fa6ac5469f 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -53,16 +53,39 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
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>())