]> granicus.if.org Git - clang/commitdiff
[arcmt] For:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 15 Jul 2011 21:11:23 +0000 (21:11 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 15 Jul 2011 21:11:23 +0000 (21:11 +0000)
id x = ...
@try {
 ...
} @finally {
 [x release];
}

Migrator will drop the release. It's better to change it to "x = 0" in a @finally to avoid leak when exception is thrown.

rdar://9398256

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

lib/ARCMigrate/TransRetainReleaseDealloc.cpp
test/ARCMT/releases.m
test/ARCMT/releases.m.result

index c72312b2600ba6d9aa271bf157601e23764c4d11..8e6c533991ec402b54d5eb9a746a2d801635d2b6 100644 (file)
@@ -97,10 +97,7 @@ public:
       return true;
     case ObjCMessageExpr::SuperInstance: {
       Transaction Trans(Pass.TA);
-      Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
-                              diag::err_unavailable,
-                              diag::err_unavailable_message,
-                              E->getSuperLoc());
+      clearDiagnostics(E->getSuperLoc());
       if (tryRemoving(E))
         return true;
       Pass.TA.replace(E->getSourceRange(), "self");
@@ -114,10 +111,17 @@ public:
     if (!rec) return true;
 
     Transaction Trans(Pass.TA);
-    Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
-                            diag::err_unavailable,
-                            diag::err_unavailable_message,
-                            rec->getExprLoc());
+    clearDiagnostics(rec->getExprLoc());
+
+    if (E->getMethodFamily() == OMF_release &&
+        isRemovable(E) && isInAtFinally(E)) {
+      // Change the -release to "receiver = 0" in a finally to avoid a leak
+      // when an exception is thrown.
+      Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
+      Pass.TA.insertAfterToken(rec->getLocEnd(), " = 0");
+      return true;
+    }
+
     if (!hasSideEffects(E, Pass.Ctx)) {
       if (tryRemoving(E))
         return true;
@@ -128,6 +132,25 @@ public:
   }
 
 private:
+  void clearDiagnostics(SourceLocation loc) const {
+    Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
+                            diag::err_unavailable,
+                            diag::err_unavailable_message,
+                            loc);
+  }
+
+  bool isInAtFinally(Expr *E) const {
+    assert(E);
+    Stmt *S = E;
+    while (S) {
+      if (isa<ObjCAtFinallyStmt>(S))
+        return true;
+      S = StmtMap->getParent(S);
+    }
+
+    return false;
+  }
+
   bool isRemovable(Expr *E) const {
     return Removables.count(E);
   }
index f49cb7e7b9d96ceeb2da62624d11da4a190e2986..74e3f47aa7b50a20cd06fd2029b095375d3886a4 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fobjc-nonfragile-abi -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fblocks -fobjc-nonfragile-abi -fsyntax-only -x objective-c %s > %t
+// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-exceptions -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
+// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fobjc-exceptions -fblocks -fobjc-nonfragile-abi -fsyntax-only -x objective-c %s > %t
 // RUN: diff %t %s.result
 
 typedef int BOOL;
@@ -36,6 +36,11 @@ id IhaveSideEffect();
   [IhaveSideEffect() release];
 
   [x release], x = 0;
+
+  @try {
+  } @finally {
+    [x release];
+  }
 }
   
 @end
index 886ce6095a0687af5633a9edcf73c0b8a79a1204..f074fb7cf7b30e7a1b3520a3cb13a6753b3779f5 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fobjc-nonfragile-abi -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
-// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fblocks -fobjc-nonfragile-abi -fsyntax-only -x objective-c %s > %t
+// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-exceptions -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
+// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fobjc-exceptions -fblocks -fobjc-nonfragile-abi -fsyntax-only -x objective-c %s > %t
 // RUN: diff %t %s.result
 
 typedef int BOOL;
@@ -34,6 +34,11 @@ id IhaveSideEffect();
   IhaveSideEffect();
 
   x = 0;
+
+  @try {
+  } @finally {
+    x = 0;
+  }
 }
   
 @end