aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp43
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp8
-rw-r--r--lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp11
-rw-r--r--lib/ARCMigrate/Transforms.cpp6
-rw-r--r--lib/ARCMigrate/Transforms.h6
-rw-r--r--test/ARCMT/GC.m29
-rw-r--r--test/ARCMT/GC.m.result24
7 files changed, 107 insertions, 20 deletions
diff --git a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 3ad05e683c..0fb7141544 100644
--- a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -196,35 +196,60 @@ static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
return true;
}
-static void removeDeallocMethod(MigrationPass &pass) {
+static void cleanupDeallocOrFinalize(MigrationPass &pass) {
ASTContext &Ctx = pass.Ctx;
TransformActions &TA = pass.TA;
DeclContext *DC = Ctx.getTranslationUnitDecl();
+ Selector FinalizeSel =
+ Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
impl_iterator;
for (impl_iterator I = impl_iterator(DC->decls_begin()),
E = impl_iterator(DC->decls_end()); I != E; ++I) {
+ ObjCMethodDecl *DeallocM = 0;
+ ObjCMethodDecl *FinalizeM = 0;
for (ObjCImplementationDecl::instmeth_iterator
MI = (*I)->instmeth_begin(),
ME = (*I)->instmeth_end(); MI != ME; ++MI) {
ObjCMethodDecl *MD = *MI;
+ if (!MD->hasBody())
+ continue;
+
if (MD->getMethodFamily() == OMF_dealloc) {
- if (MD->hasBody() &&
- isBodyEmpty(MD->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
- Transaction Trans(TA);
- TA.remove(MD->getSourceRange());
- }
- break;
+ DeallocM = MD;
+ } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
+ FinalizeM = MD;
+ }
+ }
+
+ if (DeallocM) {
+ if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
+ Transaction Trans(TA);
+ TA.remove(DeallocM->getSourceRange());
+ }
+
+ if (FinalizeM) {
+ Transaction Trans(TA);
+ TA.remove(FinalizeM->getSourceRange());
+ }
+
+ } else if (FinalizeM) {
+ if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
+ Transaction Trans(TA);
+ TA.remove(FinalizeM->getSourceRange());
+ } else {
+ Transaction Trans(TA);
+ TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
}
}
}
}
-void trans::removeEmptyStatementsAndDealloc(MigrationPass &pass) {
+void trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
- removeDeallocMethod(pass);
+ cleanupDeallocOrFinalize(pass);
for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
Transaction Trans(pass.TA);
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 394f8480e1..bf2517f119 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -36,13 +36,15 @@ class RetainReleaseDeallocRemover :
ExprSet Removables;
llvm::OwningPtr<ParentMap> StmtMap;
- Selector DelegateSel;
+ Selector DelegateSel, FinalizeSel;
public:
RetainReleaseDeallocRemover(MigrationPass &pass)
: Body(0), Pass(pass) {
DelegateSel =
Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate"));
+ FinalizeSel =
+ Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
}
void transformBody(Stmt *body) {
@@ -55,6 +57,8 @@ public:
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
switch (E->getMethodFamily()) {
default:
+ if (E->isInstanceMessage() && E->getSelector() == FinalizeSel)
+ break;
return true;
case OMF_autorelease:
if (isRemovable(E)) {
@@ -211,7 +215,7 @@ private:
} // anonymous namespace
-void trans::removeRetainReleaseDealloc(MigrationPass &pass) {
+void trans::removeRetainReleaseDeallocFinalize(MigrationPass &pass) {
BodyTransform<RetainReleaseDeallocRemover> trans(pass);
trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
diff --git a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 1dbe811149..7c533bcf3a 100644
--- a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -31,9 +31,13 @@ class ZeroOutInDeallocRemover :
llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
ImplicitParamDecl *SelfD;
ExprSet Removables;
+ Selector FinalizeSel;
public:
- ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) { }
+ ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) {
+ FinalizeSel =
+ Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
+ }
bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
ASTContext &Ctx = Pass.Ctx;
@@ -84,7 +88,8 @@ public:
}
bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
- if (D->getMethodFamily() != OMF_dealloc)
+ if (D->getMethodFamily() != OMF_dealloc &&
+ !(D->isInstanceMethod() && D->getSelector() == FinalizeSel))
return true;
if (!D->hasBody())
return true;
@@ -191,7 +196,7 @@ private:
} // anonymous namespace
-void trans::removeZeroOutPropsInDealloc(MigrationPass &pass) {
+void trans::removeZeroOutPropsInDeallocFinalize(MigrationPass &pass) {
ZeroOutInDeallocRemover trans(pass);
trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 792bb0cc9a..0decdd6b43 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -345,9 +345,9 @@ static void traverseAST(MigrationPass &pass) {
static void independentTransforms(MigrationPass &pass) {
rewriteAutoreleasePool(pass);
rewriteProperties(pass);
- removeRetainReleaseDealloc(pass);
+ removeRetainReleaseDeallocFinalize(pass);
rewriteUnusedInitDelegate(pass);
- removeZeroOutPropsInDealloc(pass);
+ removeZeroOutPropsInDeallocFinalize(pass);
makeAssignARCSafe(pass);
rewriteUnbridgedCasts(pass);
rewriteBlockObjCVariable(pass);
@@ -361,7 +361,7 @@ std::vector<TransformFn> arcmt::getAllTransformations(
transforms.push_back(independentTransforms);
// This depends on previous transformations removing various expressions.
- transforms.push_back(removeEmptyStatementsAndDealloc);
+ transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
return transforms;
}
diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h
index 0eabb21196..d935e86ae7 100644
--- a/lib/ARCMigrate/Transforms.h
+++ b/lib/ARCMigrate/Transforms.h
@@ -35,14 +35,14 @@ namespace trans {
void rewriteAutoreleasePool(MigrationPass &pass);
void rewriteUnbridgedCasts(MigrationPass &pass);
void makeAssignARCSafe(MigrationPass &pass);
-void removeRetainReleaseDealloc(MigrationPass &pass);
-void removeZeroOutPropsInDealloc(MigrationPass &pass);
+void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
+void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
void rewriteProperties(MigrationPass &pass);
void rewriteBlockObjCVariable(MigrationPass &pass);
void rewriteUnusedInitDelegate(MigrationPass &pass);
void checkAPIUses(MigrationPass &pass);
-void removeEmptyStatementsAndDealloc(MigrationPass &pass);
+void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
class BodyContext {
MigrationContext &MigrateCtx;
diff --git a/test/ARCMT/GC.m b/test/ARCMT/GC.m
index c82095c3a9..cfd22dee09 100644
--- a/test/ARCMT/GC.m
+++ b/test/ARCMT/GC.m
@@ -9,3 +9,32 @@
void test1(CFTypeRef *cft) {
id x = NSMakeCollectable(cft);
}
+
+@interface I1
+@end
+
+@implementation I1
+-(void)dealloc {
+ // dealloc
+ test1(0);
+}
+
+-(void)finalize {
+ // finalize
+ test1(0);
+}
+@end
+
+@interface I2
+@property (retain) id prop;
+@end
+
+@implementation I2
+@synthesize prop;
+
+-(void)finalize {
+ self.prop = 0;
+ // finalize
+ test1(0);
+}
+@end
diff --git a/test/ARCMT/GC.m.result b/test/ARCMT/GC.m.result
index cdf6431dbf..a492f02970 100644
--- a/test/ARCMT/GC.m.result
+++ b/test/ARCMT/GC.m.result
@@ -9,3 +9,27 @@
void test1(CFTypeRef *cft) {
id x = CFBridgingRelease(cft);
}
+
+@interface I1
+@end
+
+@implementation I1
+-(void)dealloc {
+ // dealloc
+ test1(0);
+}
+
+@end
+
+@interface I2
+@property id prop;
+@end
+
+@implementation I2
+@synthesize prop;
+
+-(void)dealloc {
+ // finalize
+ test1(0);
+}
+@end