Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixes incorrect codegen when devirtualization is aborted due to covariant return types.

Differential Revision: http://reviews.llvm.org/D5321

llvm-svn: 218602
  • Loading branch information
alexey-bataev committed Sep 29, 2014
1 parent 609e2e6 commit 5bd6879
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 13 deletions.
19 changes: 9 additions & 10 deletions clang/lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down

0 comments on commit 5bd6879

Please sign in to comment.