aboutsummaryrefslogtreecommitdiff
path: root/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ARCMigrate/TransRetainReleaseDealloc.cpp')
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp39
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);
}