aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGExprCXX.cpp18
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp12
2 files changed, 29 insertions, 1 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index fa6ac5469f..99c54f0456 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -54,7 +54,23 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
}
static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) {
- QualType DerivedType = Base->IgnoreParenCasts()->getType();
+ const Expr *E = Base;
+
+ 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 (const PointerType *PTy = DerivedType->getAs<PointerType>())
DerivedType = PTy->getPointeeType();
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
index 08a94903d5..3de75ed3db 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -36,4 +36,16 @@ namespace Test3 {
// CHECK: call i32 @_ZN5Test31A1fEv
return b->f();
}
+
+ // CHECK: define i32 @_ZN5Test31fERNS_1BE
+ int f(B &b) {
+ // CHECK: call i32 @_ZN5Test31A1fEv
+ return b.f();
+ }
+
+ // CHECK: define i32 @_ZN5Test31fEPv
+ int f(void *v) {
+ // CHECK: call i32 @_ZN5Test31A1fEv
+ return static_cast<B*>(v)->f();
+ }
}