aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprCXX.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-06-28 01:56:38 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-06-28 01:56:38 +0000
commit632fbaa22fbed7c090eb83775731bfff786c2198 (patch)
treee02eebca83c243b7b6dcb3be7a12807ea22cdb43 /lib/CodeGen/CGExprCXX.cpp
parentd558b5238df74ef3cb76d7125375a5c28fe0eaa9 (diff)
Fix another issue with devirtualizing calls to final methods by passing them
the correct this pointer. There is some potential for sharing a bit more code with canDevirtualizeMemberFunctionCalls, but that can be done in an independent patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159326 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r--lib/CodeGen/CGExprCXX.cpp25
1 files changed, 16 insertions, 9 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 30324b97ef..a39e82408d 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -172,11 +172,21 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
}
// Compute the object pointer.
+ const Expr *Base = ME->getBase();
+ bool CanUseVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+ bool Devirtualize = CanUseVirtualCall &&
+ canDevirtualizeMemberFunctionCalls(getContext(), Base, MD);
+
+ const Expr *Inner = Base;
+ if (Devirtualize)
+ Inner = Base->ignoreParenBaseCasts();
+
llvm::Value *This;
if (ME->isArrow())
- This = EmitScalarExpr(ME->getBase());
+ This = EmitScalarExpr(Inner);
else
- This = EmitLValue(ME->getBase()).getAddress();
+ This = EmitLValue(Inner).getAddress();
+
if (MD->isTrivial()) {
if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
@@ -223,11 +233,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
//
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
- const Expr *Base = ME->getBase();
- bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
- && !canDevirtualizeMemberFunctionCalls(getContext(),
- Base, MD);
- const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
+ bool UseVirtualCall = CanUseVirtualCall && !Devirtualize;
+ const CXXRecordDecl *MostDerivedClassDecl = Inner->getBestDynamicClassType();
llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
@@ -238,7 +245,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
MD->isVirtual() &&
ME->hasQualifier())
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
- else if (ME->hasQualifier())
+ else if (!Devirtualize)
Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
else {
const CXXMethodDecl *DM =
@@ -258,7 +265,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
MD->isVirtual() &&
ME->hasQualifier())
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
- else if (ME->hasQualifier())
+ else if (!Devirtualize)
Callee = CGM.GetAddrOfFunction(MD, Ty);
else {
const CXXMethodDecl *DerivedMethod =