]> granicus.if.org Git - clang/commitdiff
Debug info: Improve line table for functions with cleanups an early exit
authorAdrian Prantl <aprantl@apple.com>
Tue, 29 Apr 2014 01:07:59 +0000 (01:07 +0000)
committerAdrian Prantl <aprantl@apple.com>
Tue, 29 Apr 2014 01:07:59 +0000 (01:07 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207480 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenFunction.cpp
test/CodeGenObjC/arc-linetable.m

index 95e4ee498d23caf93fdf2402e54e6e2e65362880..e8f48afb3b5a8231097bead1e77064e02b262c52 100644 (file)
@@ -498,6 +498,22 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
   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,
                                     QualType RetTy,
                                     llvm::Function *Fn,
@@ -593,6 +609,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
   if (RetTy->isVoidType()) {
     // Void type; nothing to return.
     ReturnValue = 0;
+
+    // Count the implicit return.
+    if (!endsWithReturn(D))
+      ++NumReturnExprs;
   } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
              !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
     // Indirect aggregate return; emit returned value directly into sret slot.
index 7af02edc5b62b6329d83bbe9ef0a715113a28fbf..20a3de78f47fadd06499e68b87851f35dd9333fc 100644 (file)
 // CHECK: @objc_msgSend{{.*}} !dbg ![[MSG7:[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
 + (id)alloc;
   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