forked from OSchip/llvm-project
Fix bug 20116 - http://llvm.org/bugs/show_bug.cgi?id=20116
Fixes incorrect codegen when devirtualization is aborted due to covariant return types. Differential Revision: http://reviews.llvm.org/D5321 llvm-svn: 218602
This commit is contained in:
parent
609e2e6a6e
commit
5bd6879439
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue