diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-06-28 01:56:38 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-06-28 01:56:38 +0000 |
commit | 632fbaa22fbed7c090eb83775731bfff786c2198 (patch) | |
tree | e02eebca83c243b7b6dcb3be7a12807ea22cdb43 /lib/CodeGen/CGExprCXX.cpp | |
parent | d558b5238df74ef3cb76d7125375a5c28fe0eaa9 (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.cpp | 25 |
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 = |