[cfe-commits] r171454 - in /cfe/trunk: lib/ARCMigrate/TransUnbridgedCasts.cpp test/ARCMT/Common.h test/ARCMT/block_copy_release.m test/ARCMT/block_copy_release.m.result

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Jan 2 19:17:19 PST 2013


Author: akirtzidis
Date: Wed Jan  2 21:17:17 2013
New Revision: 171454

URL: http://llvm.org/viewvc/llvm-project?rev=171454&view=rev
Log:
[arcmt] Rewrite uses of Block_copy/Block_release macros.

  c = Block_copy(b);
  Block_release(c);
 ---->
  c = [b copy];
  <removed>

rdar://9408211

Added:
    cfe/trunk/test/ARCMT/block_copy_release.m
    cfe/trunk/test/ARCMT/block_copy_release.m.result
Modified:
    cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp
    cfe/trunk/test/ARCMT/Common.h

Modified: cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp?rev=171454&r1=171453&r2=171454&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransUnbridgedCasts.cpp Wed Jan  2 21:17:17 2013
@@ -30,6 +30,14 @@
 // ---->
 //  CFStringRef str = (__bridge CFStringRef)self;
 //
+// Uses of Block_copy/Block_release macros are rewritten:
+//
+//  c = Block_copy(b);
+//  Block_release(c);
+// ---->
+//  c = [b copy];
+//  <removed>
+//
 //===----------------------------------------------------------------------===//
 
 #include "Transforms.h"
@@ -54,32 +62,32 @@
   IdentifierInfo *SelfII;
   OwningPtr<ParentMap> StmtMap;
   Decl *ParentD;
+  Stmt *Body;
+  mutable OwningPtr<ExprSet> Removables;
 
 public:
-  UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0) {
+  UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0), Body(0) {
     SelfII = &Pass.Ctx.Idents.get("self");
   }
 
   void transformBody(Stmt *body, Decl *ParentD) {
     this->ParentD = ParentD;
+    Body = body;
     StmtMap.reset(new ParentMap(body));
     TraverseStmt(body);
   }
 
   bool VisitCastExpr(CastExpr *E) {
-    if (E->getCastKind() != CK_CPointerToObjCPointerCast
-        && E->getCastKind() != CK_BitCast)
+    if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
+        E->getCastKind() != CK_BitCast &&
+        E->getCastKind() != CK_AnyPointerToBlockPointerCast)
       return true;
 
     QualType castType = E->getType();
     Expr *castExpr = E->getSubExpr();
     QualType castExprType = castExpr->getType();
 
-    if (castType->isObjCObjectPointerType() &&
-        castExprType->isObjCObjectPointerType())
-      return true;
-    if (!castType->isObjCObjectPointerType() &&
-        !castExprType->isObjCObjectPointerType())
+    if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
       return true;
     
     bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
@@ -94,7 +102,7 @@
     if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
       return true;
 
-    if (castType->isObjCObjectPointerType())
+    if (castType->isObjCRetainableType())
       transformNonObjCToObjCCast(E);
     else
       transformObjCToNonObjCCast(E);
@@ -263,7 +271,78 @@
     rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
   }
 
+  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
+    SourceManager &SM = Pass.Ctx.getSourceManager();
+    SourceLocation Loc = E->getExprLoc();
+    assert(Loc.isMacroID());
+    SourceLocation MacroBegin, MacroEnd;
+    llvm::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
+    SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
+    SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
+    SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
+
+    Outer = SourceRange(MacroBegin, MacroEnd);
+    Inner = SourceRange(InnerBegin, InnerEnd);
+  }
+
+  void rewriteBlockCopyMacro(CastExpr *E) {
+    SourceRange OuterRange, InnerRange;
+    getBlockMacroRanges(E, OuterRange, InnerRange);
+
+    Transaction Trans(Pass.TA);
+    Pass.TA.replace(OuterRange, InnerRange);
+    Pass.TA.insert(InnerRange.getBegin(), "[");
+    Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
+    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
+                            diag::err_arc_cast_requires_bridge,
+                            OuterRange);
+  }
+
+  void removeBlockReleaseMacro(CastExpr *E) {
+    SourceRange OuterRange, InnerRange;
+    getBlockMacroRanges(E, OuterRange, InnerRange);
+
+    Transaction Trans(Pass.TA);
+    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
+                            diag::err_arc_cast_requires_bridge,
+                            OuterRange);
+    if (!hasSideEffects(E, Pass.Ctx)) {
+      if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
+        return;
+    }
+    Pass.TA.replace(OuterRange, InnerRange);
+  }
+
+  bool tryRemoving(Expr *E) const {
+    if (!Removables) {
+      Removables.reset(new ExprSet);
+      collectRemovables(Body, *Removables);
+    }
+
+    if (Removables->count(E)) {
+      Pass.TA.removeStmt(E);
+      return true;
+    }
+
+    return false;
+  }
+
   void transformObjCToNonObjCCast(CastExpr *E) {
+    SourceLocation CastLoc = E->getExprLoc();
+    if (CastLoc.isMacroID()) {
+      StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
+                                                    Pass.Ctx.getSourceManager(),
+                                                    Pass.Ctx.getLangOpts());
+      if (MacroName == "Block_copy") {
+        rewriteBlockCopyMacro(E);
+        return;
+      }
+      if (MacroName == "Block_release") {
+        removeBlockReleaseMacro(E);
+        return;
+      }
+    }
+
     if (isSelf(E->getSubExpr()))
       return rewriteToBridgedCast(E, OBC_Bridge);
 

Modified: cfe/trunk/test/ARCMT/Common.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/Common.h?rev=171454&r1=171453&r2=171454&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/Common.h (original)
+++ cfe/trunk/test/ARCMT/Common.h Wed Jan  2 21:17:17 2013
@@ -10,6 +10,7 @@
 
 #define NS_INLINE static __inline__ __attribute__((always_inline))
 #define nil ((void*) 0)
+#define NULL ((void*)0)
 
 typedef int BOOL;
 typedef unsigned NSUInteger;
@@ -102,3 +103,8 @@
 }
 
 #endif
+
+void *_Block_copy(const void *aBlock);
+void _Block_release(const void *aBlock);
+#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
+#define Block_release(...) _Block_release((const void *)(__VA_ARGS__))

Added: cfe/trunk/test/ARCMT/block_copy_release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/block_copy_release.m?rev=171454&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/block_copy_release.m (added)
+++ cfe/trunk/test/ARCMT/block_copy_release.m Wed Jan  2 21:17:17 2013
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
+// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fblocks -fsyntax-only -x objective-c %s > %t
+// RUN: diff %t %s.result
+
+#include "Common.h"
+
+typedef void (^blk)(int);
+
+void func(blk b) {
+  blk c = Block_copy(b);
+  Block_release(c);
+}
+
+void func2(id b) {
+  id c = Block_copy(b);
+  Block_release(c);
+}

Added: cfe/trunk/test/ARCMT/block_copy_release.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/block_copy_release.m.result?rev=171454&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/block_copy_release.m.result (added)
+++ cfe/trunk/test/ARCMT/block_copy_release.m.result Wed Jan  2 21:17:17 2013
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fblocks -fsyntax-only -fobjc-arc -x objective-c %s.result
+// RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fblocks -fsyntax-only -x objective-c %s > %t
+// RUN: diff %t %s.result
+
+#include "Common.h"
+
+typedef void (^blk)(int);
+
+void func(blk b) {
+  blk c = [b copy];
+}
+
+void func2(id b) {
+  id c = [b copy];
+}





More information about the cfe-commits mailing list