diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-15 21:11:23 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-15 21:11:23 +0000 |
commit | f55a869ba4c651943715d13d9b9c50a2e752a6ac (patch) | |
tree | b7d8706ff091c6be17e529d45833cd2daf2622bc /lib/ARCMigrate/TransRetainReleaseDealloc.cpp | |
parent | fc71ac810f6bb4fd37b8558ad1ef834f9119ab42 (diff) |
[arcmt] For:
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
Diffstat (limited to 'lib/ARCMigrate/TransRetainReleaseDealloc.cpp')
-rw-r--r-- | lib/ARCMigrate/TransRetainReleaseDealloc.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index c72312b260..8e6c533991 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -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); } |