aboutsummaryrefslogtreecommitdiff
path: root/lib
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
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')
-rw-r--r--lib/AST/Expr.cpp38
-rw-r--r--lib/CodeGen/CGExprCXX.cpp25
2 files changed, 38 insertions, 25 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 15cf6602b7..b68f864711 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -34,21 +34,7 @@
using namespace clang;
const CXXRecordDecl *Expr::getBestDynamicClassType() const {
- const Expr *E = this;
-
- while (true) {
- E = E->IgnoreParens();
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase ||
- CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
-
- break;
- }
+ const Expr *E = ignoreParenBaseCasts();
QualType DerivedType = E->getType();
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
@@ -2231,7 +2217,27 @@ Expr *Expr::IgnoreParenLValueCasts() {
}
return E;
}
-
+
+Expr *Expr::ignoreParenBaseCasts() {
+ Expr *E = this;
+ while (true) {
+ if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase ||
+ CE->getCastKind() == CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ }
+
+ return E;
+ }
+}
+
Expr *Expr::IgnoreParenImpCasts() {
Expr *E = this;
while (true) {
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 =