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 | 6a8a14d217cd4f26d8f72f48234d092fde0213fd (patch) | |
tree | d1016c4f8e4a110bbbeed56fd46bedfea694964e /clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp | |
parent | 653b51a93803622c004d0e587e8bf4cdb8f7324a (diff) | |
download | bcm5719-llvm-6a8a14d217cd4f26d8f72f48234d092fde0213fd.tar.gz bcm5719-llvm-6a8a14d217cd4f26d8f72f48234d092fde0213fd.zip |
[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
llvm-svn: 135301
Diffstat (limited to 'clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp')
-rw-r--r-- | clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index c72312b2600..8e6c533991e 100644 --- a/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/clang/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); } |