From: Fariborz Jahanian Date: Thu, 26 Jan 2012 20:57:58 +0000 (+0000) Subject: objc-arc: introduce -no-finalize-removal which in gc mode, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bbdfad581fa300fa0d162d968ec14de3c95fc760;p=clang objc-arc: introduce -no-finalize-removal which in gc mode, leaves "finalize' behind and in arc mode, does not include it. This allows the migrated source to be compiled in both gc and arc mode. // rdar://10532441 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149079 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index b05dd4c95d..738a00dcd0 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -78,7 +78,8 @@ bool getFileRemappings(std::vector > &remap, typedef void (*TransformFn)(MigrationPass &pass); -std::vector getAllTransformations(LangOptions::GCMode OrigGCMode); +std::vector getAllTransformations(LangOptions::GCMode OrigGCMode, + bool NoFinalizeRemoval); class MigrationProcess { CompilerInvocation OrigCI; diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp index cd4835ef39..f9a1a75d87 100644 --- a/lib/ARCMigrate/ARCMT.cpp +++ b/lib/ARCMigrate/ARCMT.cpp @@ -232,7 +232,8 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError; bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; - std::vector transforms = arcmt::getAllTransformations(OrigGCMode); + std::vector transforms = arcmt::getAllTransformations(OrigGCMode, + NoFinalizeRemoval); assert(!transforms.empty()); llvm::OwningPtr CInvok; @@ -337,8 +338,10 @@ static bool applyTransforms(CompilerInvocation &origCI, CInvok.getFrontendOpts().Inputs.push_back(Input); MigrationProcess migration(CInvok, DiagClient, outputDir); + bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; - std::vector transforms = arcmt::getAllTransformations(OrigGCMode); + std::vector transforms = arcmt::getAllTransformations(OrigGCMode, + NoFinalizeRemoval); assert(!transforms.empty()); for (unsigned i=0, e = transforms.size(); i != e; ++i) { diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index a64124015c..91121f0245 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -502,6 +502,45 @@ void MigrationContext::traverse(TranslationUnitDecl *TU) { ASTTransform(*this).TraverseDecl(TU); } +static void GCRewriteFinalize(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 + impl_iterator; + for (impl_iterator I = impl_iterator(DC->decls_begin()), + E = impl_iterator(DC->decls_end()); I != E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator + MI = (*I)->instmeth_begin(), + ME = (*I)->instmeth_end(); MI != ME; ++MI) { + ObjCMethodDecl *MD = *MI; + if (!MD->hasBody()) + continue; + + if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) { + ObjCMethodDecl *FinalizeM = MD; + Transaction Trans(TA); + TA.insert(FinalizeM->getSourceRange().getBegin(), + "#if !__has_feature(objc_arc)\n"); + CharSourceRange::getTokenRange(FinalizeM->getSourceRange()); + const SourceManager &SM = pass.Ctx.getSourceManager(); + const LangOptions &LangOpts = pass.Ctx.getLangOptions(); + bool Invalid; + std::string str = "\n#endif\n"; + str += Lexer::getSourceText( + CharSourceRange::getTokenRange(FinalizeM->getSourceRange()), + SM, LangOpts, &Invalid); + TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str); + + break; + } + } + } +} + //===----------------------------------------------------------------------===// // getAllTransformations. //===----------------------------------------------------------------------===// @@ -531,9 +570,12 @@ static void independentTransforms(MigrationPass &pass) { } std::vector arcmt::getAllTransformations( - LangOptions::GCMode OrigGCMode) { + LangOptions::GCMode OrigGCMode, + bool NoFinalizeRemoval) { std::vector transforms; + if (OrigGCMode == LangOptions::GCOnly && NoFinalizeRemoval) + transforms.push_back(GCRewriteFinalize); transforms.push_back(independentTransforms); // This depends on previous transformations removing various expressions. transforms.push_back(removeEmptyStatementsAndDeallocFinalize); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5a0117af5a..a189155e12 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1065,6 +1065,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) { Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error); + Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal); return true; } diff --git a/test/ARCMT/GC-no-finalize-removal.m b/test/ARCMT/GC-no-finalize-removal.m new file mode 100644 index 0000000000..d9739376f2 --- /dev/null +++ b/test/ARCMT/GC-no-finalize-removal.m @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -x objective-c %s.result +// RUN: arcmt-test --args -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-gc-only -no-finalize-removal -x objective-c %s > %t +// RUN: diff %t %s.result +// RUN: arcmt-test --args -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-gc-only -no-finalize-removal -x objective-c++ %s > %t +// RUN: diff %t %s.result +// DISABLE: mingw32 + +#include "Common.h" +#include "GC.h" + +void test1(CFTypeRef *cft) { + id x = NSMakeCollectable(cft); +} + +@interface I1 { + __strong I1 *myivar; +} +@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 + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface QQ { + __weak id s; + __weak QQ *q; +} +@end + +@interface I3 +@property (assign) I3 *__weak pw1, *__weak pw2; +@property (assign) I3 *__strong ps; +@property (assign) I3 * pds; +@end + +@interface I4Impl { + I4Impl *pds2; + I4Impl *pds3; + __weak I4Impl *pw3; + __weak I4Impl *pw4; +} +@property (assign) I4Impl *__weak pw1, *__weak pw2; +@property (assign) I4Impl *__strong ps; +@property (assign) I4Impl * pds; +@property (assign) I4Impl * pds2; +@property (readwrite) I4Impl * pds3; +@property (readonly) I4Impl * pds4; +@property (readonly) __weak I4Impl *pw3; +@property (assign) __weak I4Impl *pw4; +@end + +@implementation I4Impl +@synthesize pw1, pw2, pw3, pw4, ps, pds, pds2, pds3, pds4; + +-(void)test1:(CFTypeRef *)cft { + id x = NSMakeCollectable(cft); +} +@end + +// rdar://10532449 +@interface rdar10532449 +@property (assign) id assign_prop; +@property (assign, readonly) id __strong strong_readonly_prop; +@property (assign) id __weak weak_prop; +@end + +@implementation rdar10532449 +@synthesize assign_prop, strong_readonly_prop, weak_prop; +@end diff --git a/test/ARCMT/GC-no-finalize-removal.m.result b/test/ARCMT/GC-no-finalize-removal.m.result new file mode 100644 index 0000000000..38aabc32ae --- /dev/null +++ b/test/ARCMT/GC-no-finalize-removal.m.result @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -x objective-c %s.result +// RUN: arcmt-test --args -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-gc-only -no-finalize-removal -x objective-c %s > %t +// RUN: diff %t %s.result +// RUN: arcmt-test --args -triple x86_64-apple-macosx10.7 -fsyntax-only -fobjc-gc-only -no-finalize-removal -x objective-c++ %s > %t +// RUN: diff %t %s.result +// DISABLE: mingw32 + +#include "Common.h" +#include "GC.h" + +void test1(CFTypeRef *cft) { + id x = CFBridgingRelease(cft); +} + +@interface I1 { + I1 *myivar; +} +@end + +@implementation I1 +-(void)dealloc { + // dealloc + test1(0); +} + +#if !__has_feature(objc_arc) +-(void)finalize { + // finalize + test1(0); +} +#endif +@end + +@interface I2 +@property (strong) id prop; +@end + +@implementation I2 +@synthesize prop; + +#if !__has_feature(objc_arc) +-(void)finalize { + self.prop = 0; + // finalize + test1(0); +} +#endif +-(void)dealloc { + // finalize + test1(0); +} +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface QQ { + __weak id s; + __unsafe_unretained QQ *q; +} +@end + +@interface I3 +@property (weak) I3 * pw1, * pw2; +@property (strong) I3 * ps; +@property (assign) I3 * pds; +@end + +@interface I4Impl { + I4Impl *__strong pds2; + I4Impl *pds3; + __weak I4Impl *pw3; + __weak I4Impl *pw4; +} +@property (weak) I4Impl * pw1, * pw2; +@property (strong) I4Impl * ps; +@property (strong) I4Impl * pds; +@property (strong) I4Impl * pds2; +@property (readwrite) I4Impl * pds3; +@property (readonly) I4Impl * pds4; +@property (weak, readonly) I4Impl *pw3; +@property (weak) I4Impl *pw4; +@end + +@implementation I4Impl +@synthesize pw1, pw2, pw3, pw4, ps, pds, pds2, pds3, pds4; + +-(void)test1:(CFTypeRef *)cft { + id x = CFBridgingRelease(cft); +} +@end + +// rdar://10532449 +@interface rdar10532449 +@property (strong) id assign_prop; +@property (strong, readonly) id strong_readonly_prop; +@property (weak) id weak_prop; +@end + +@implementation rdar10532449 +@synthesize assign_prop, strong_readonly_prop, weak_prop; +@end diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp index 9523ebcba0..6efb707950 100644 --- a/tools/arcmt-test/arcmt-test.cpp +++ b/tools/arcmt-test/arcmt-test.cpp @@ -173,7 +173,8 @@ static bool performTransformations(StringRef resourcesPath, MigrationProcess migration(origCI, DiagClient); std::vector - transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC()); + transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(), + origCI.getMigratorOpts().NoFinalizeRemoval); assert(!transforms.empty()); llvm::OwningPtr transformPrinter;