Debug info: Improve line table for functions with cleanups an early exit

and no return expr at the end of the function.
The "function has only simple returns" check in FinishFunction tests
whether the number of simple return exprs equals the number of return
exprs, but so far a fallthrough at the end of a function was not counted
as a return, which would result in cleanup code being associated with the
wrong source line.

rdar://problem/16733984.

llvm-svn: 207480
This commit is contained in:
Adrian Prantl 2014-04-29 01:07:59 +00:00
parent c829f19e24
commit 2cede0f92c
2 changed files with 45 additions and 0 deletions

View File

@ -498,6 +498,22 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
OpenCLKernelMetadata->addOperand(kernelMDNode); OpenCLKernelMetadata->addOperand(kernelMDNode);
} }
/// Determine whether the function F ends with a return stmt.
static bool endsWithReturn(const Decl* F) {
const Stmt *Body = nullptr;
if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
Body = FD->getBody();
else if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(F))
Body = OMD->getBody();
if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
auto LastStmt = CS->body_rbegin();
if (LastStmt != CS->body_rend())
return isa<ReturnStmt>(*LastStmt);
}
return false;
}
void CodeGenFunction::StartFunction(GlobalDecl GD, void CodeGenFunction::StartFunction(GlobalDecl GD,
QualType RetTy, QualType RetTy,
llvm::Function *Fn, llvm::Function *Fn,
@ -593,6 +609,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (RetTy->isVoidType()) { if (RetTy->isVoidType()) {
// Void type; nothing to return. // Void type; nothing to return.
ReturnValue = 0; ReturnValue = 0;
// Count the implicit return.
if (!endsWithReturn(D))
++NumReturnExprs;
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType())) { !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Indirect aggregate return; emit returned value directly into sret slot. // Indirect aggregate return; emit returned value directly into sret slot.

View File

@ -32,6 +32,15 @@
// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG7:[0-9]+]] // CHECK: @objc_msgSend{{.*}} !dbg ![[MSG7:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[RET7:[0-9]+]] // CHECK: ret {{.*}} !dbg ![[RET7:[0-9]+]]
// CHECK: define {{.*}}testCleanupVoid
// CHECK: icmp ne {{.*}}!dbg ![[SKIP1:[0-9]+]]
// CHECK-NEXT: br {{.*}}, label %[[CLEANUP:.*]], label
// CHECK: [[CLEANUP]]:
// CHECK-NEXT: !dbg ![[RET8:[0-9]+]]
// CHECK: @objc_storeStrong{{.*}}, !dbg ![[ARC8:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[RET8]]
typedef signed char BOOL;
@interface NSObject @interface NSObject
+ (id)alloc; + (id)alloc;
@ -93,6 +102,22 @@
return 1; return 1;
} }
- (void)testCleanupVoid:(BOOL)skip withDelegate: (AppDelegate *) delegate {
static BOOL skip_all;
// CHECK: ![[SKIP1]] = metadata !{i32 [[@LINE+1]], i32 0,
if (!skip_all) {
if (!skip) {
return;
}
NSString *s = @"bar";
if (!skip) {
[delegate testVoid :s];
}
}
// CHECK: ![[RET8]] = metadata !{i32 [[@LINE+2]], i32 0,
// CHECK: ![[ARC8]] = metadata !{i32 [[@LINE+1]], i32 0,
}
@end @end