]> granicus.if.org Git - clang/commitdiff
objc-arc: introduce -no-finalize-removal which in gc mode,
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 26 Jan 2012 20:57:58 +0000 (20:57 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 26 Jan 2012 20:57:58 +0000 (20:57 +0000)
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

include/clang/ARCMigrate/ARCMT.h
lib/ARCMigrate/ARCMT.cpp
lib/ARCMigrate/Transforms.cpp
lib/Frontend/CompilerInvocation.cpp
test/ARCMT/GC-no-finalize-removal.m [new file with mode: 0644]
test/ARCMT/GC-no-finalize-removal.m.result [new file with mode: 0644]
tools/arcmt-test/arcmt-test.cpp

index b05dd4c95d2d89314b492d305321c4dc458cf883..738a00dcd01d757018bc5ff3b8c1d95c0df07e0e 100644 (file)
@@ -78,7 +78,8 @@ bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
 
 typedef void (*TransformFn)(MigrationPass &pass);
 
-std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode);
+std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode,
+                                               bool NoFinalizeRemoval);
 
 class MigrationProcess {
   CompilerInvocation OrigCI;
index cd4835ef3915feb33aef4dfe81f7a4c36a96f3f6..f9a1a75d87703199677cdb64c8811a84e1b90c42 100644 (file)
@@ -232,7 +232,8 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
   bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
   bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
 
-  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode);
+  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
+                                                                     NoFinalizeRemoval);
   assert(!transforms.empty());
 
   llvm::OwningPtr<CompilerInvocation> 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<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode);
+  std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
+                                                                     NoFinalizeRemoval);
   assert(!transforms.empty());
 
   for (unsigned i=0, e = transforms.size(); i != e; ++i) {
index a64124015cf62bd82dc330952f21eb788f9e91cf..91121f02453d900d74e7108ec4fe2b3b26dd069b 100644 (file)
@@ -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<ObjCImplementationDecl>
+  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<TransformFn> arcmt::getAllTransformations(
-                                               LangOptions::GCMode OrigGCMode) {
+                                               LangOptions::GCMode OrigGCMode,
+                                               bool NoFinalizeRemoval) {
   std::vector<TransformFn> 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);
index 5a0117af5a96d7b33b61964f7d63b772dcd3f85c..a189155e12dc3873b45c0f3fd85755fed53b7ee5 100644 (file)
@@ -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 (file)
index 0000000..d973937
--- /dev/null
@@ -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 (file)
index 0000000..38aabc3
--- /dev/null
@@ -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
index 9523ebcba05d2733cd2287bf5b4766a4b18cfed5..6efb707950086103a3966d4392b3a7b357644f0d 100644 (file)
@@ -173,7 +173,8 @@ static bool performTransformations(StringRef resourcesPath,
   MigrationProcess migration(origCI, DiagClient);
 
   std::vector<TransformFn>
-    transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC());
+    transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(),
+                                 origCI.getMigratorOpts().NoFinalizeRemoval);
   assert(!transforms.empty());
 
   llvm::OwningPtr<PrintTransforms> transformPrinter;