summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp19
-rw-r--r--clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp9
2 files changed, 15 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 7d41af40f6a..483966fce20 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -110,7 +110,15 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
assert(DevirtualizedMethod);
const CXXRecordDecl *DevirtualizedClass = DevirtualizedMethod->getParent();
const Expr *Inner = Base->ignoreParenBaseCasts();
- if (getCXXRecord(Inner) == DevirtualizedClass)
+ if (DevirtualizedMethod->getReturnType().getCanonicalType() !=
+ MD->getReturnType().getCanonicalType())
+ // If the return types are not the same, this might be a case where more
+ // code needs to run to compensate for it. For example, the derived
+ // method might return a type that inherits form from the return
+ // type of MD and has a prefix.
+ // For now we just avoid devirtualizing these covariant cases.
+ DevirtualizedMethod = nullptr;
+ else if (getCXXRecord(Inner) == DevirtualizedClass)
// If the class of the Inner expression is where the dynamic method
// is defined, build the this pointer from it.
Base = Inner;
@@ -121,15 +129,6 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
// we don't have support for that yet, so do a virtual call.
DevirtualizedMethod = nullptr;
}
- // If the return types are not the same, this might be a case where more
- // code needs to run to compensate for it. For example, the derived
- // method might return a type that inherits form from the return
- // type of MD and has a prefix.
- // For now we just avoid devirtualizing these covariant cases.
- if (DevirtualizedMethod &&
- DevirtualizedMethod->getReturnType().getCanonicalType() !=
- MD->getReturnType().getCanonicalType())
- DevirtualizedMethod = nullptr;
}
llvm::Value *This;
diff --git a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
index 11026e8df3e..89c9a61b36e 100644
--- a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -178,9 +178,12 @@ namespace Test9 {
A *f(RC *x) {
// FIXME: It should be possible to devirtualize this case, but that is
// not implemented yet.
- // CHECK: getelementptr
- // CHECK-NEXT: %[[FUNC:.*]] = load
- // CHECK-NEXT: bitcast
+ // CHECK: load
+ // CHECK: bitcast
+ // CHECK: [[F_PTR_RA:%.+]] = bitcast
+ // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
+ // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0
+ // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
// CHECK-NEXT: = call {{.*}} %[[FUNC]]
return static_cast<RA*>(x)->f();
}
OpenPOWER on IntegriCloud