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);
|
assert(DevirtualizedMethod);
|
||||||
const CXXRecordDecl *DevirtualizedClass = DevirtualizedMethod->getParent();
|
const CXXRecordDecl *DevirtualizedClass = DevirtualizedMethod->getParent();
|
||||||
const Expr *Inner = Base->ignoreParenBaseCasts();
|
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
|
// If the class of the Inner expression is where the dynamic method
|
||||||
// is defined, build the this pointer from it.
|
// is defined, build the this pointer from it.
|
||||||
Base = Inner;
|
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.
|
// we don't have support for that yet, so do a virtual call.
|
||||||
DevirtualizedMethod = nullptr;
|
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;
|
llvm::Value *This;
|
||||||
|
|
|
@ -178,9 +178,12 @@ namespace Test9 {
|
||||||
A *f(RC *x) {
|
A *f(RC *x) {
|
||||||
// FIXME: It should be possible to devirtualize this case, but that is
|
// FIXME: It should be possible to devirtualize this case, but that is
|
||||||
// not implemented yet.
|
// not implemented yet.
|
||||||
// CHECK: getelementptr
|
// CHECK: load
|
||||||
// CHECK-NEXT: %[[FUNC:.*]] = load
|
// CHECK: bitcast
|
||||||
// CHECK-NEXT: 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]]
|
// CHECK-NEXT: = call {{.*}} %[[FUNC]]
|
||||||
return static_cast<RA*>(x)->f();
|
return static_cast<RA*>(x)->f();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue