aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-06-26 17:45:31 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-06-26 17:45:31 +0000
commit0b4fe503ef00d9f8ea330850d3e3b303e9c7c876 (patch)
tree4ea4cf2da2635676660fe4ed9c1ece8d0994a03d /lib/Sema/SemaExpr.cpp
parent7ed4f663287b087bc566d29d9febdfdeb8dd2776 (diff)
During codegen of a virtual call we would extract any casts in the expression
to see if we had an underlying final class or method, but we would then use the cast type to do the call, resulting in a direct call to the wrong method. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159212 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp16
1 files changed, 16 insertions, 0 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 07f3c1d6c7..4dd6f0b552 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -10844,6 +10844,22 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
}
SemaRef.MarkAnyDeclReferenced(Loc, D);
+
+ // If this is a call to a method via a cast, also mark the method in the
+ // derived class used in case codegen can devirtualize the call.
+ const MemberExpr *ME = dyn_cast<MemberExpr>(E);
+ if (!ME)
+ return;
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
+ if (!MD)
+ return;
+ const Expr *Base = ME->getBase();
+ const CXXRecordDecl *MostDerivedClassDecl
+ = Base->getMostDerivedClassDeclForType();
+ if (!MostDerivedClassDecl)
+ return;
+ CXXMethodDecl *DM = MD->getCorrespondingMethodInClass(MostDerivedClassDecl);
+ SemaRef.MarkAnyDeclReferenced(Loc, DM);
}
/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.