aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Expr.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/AST/Expr.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/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 3de4b5771a..22d15be6a8 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -33,6 +33,37 @@
#include <cstring>
using namespace clang;
+const CXXRecordDecl *Expr::getMostDerivedClassDeclForType() 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;
+ }
+
+ QualType DerivedType = E->getType();
+ if (DerivedType->isDependentType())
+ return NULL;
+ if (const PointerType *PTy = DerivedType->getAs<PointerType>())
+ DerivedType = PTy->getPointeeType();
+
+ const RecordType *Ty = DerivedType->castAs<RecordType>();
+ if (!Ty)
+ return NULL;
+
+ Decl *D = Ty->getDecl();
+ return cast<CXXRecordDecl>(D);
+}
+
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
/// but also int expressions which are produced by things like comparisons in