diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-01-03 03:17:17 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-01-03 03:17:17 +0000 |
commit | 5d2faa41bc63a2a29535ae3dbbc99daabf14ea2f (patch) | |
tree | 29e76dc61bf421354bccb9e21a4a2d80129992d7 | |
parent | bcde478a5f2600718a225eade94549c9792166b8 (diff) |
[arcmt] Rewrite uses of Block_copy/Block_release macros.
c = Block_copy(b);
Block_release(c);
---->
c = [b copy];
<removed>
rdar://9408211
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171454 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/ARCMigrate/TransUnbridgedCasts.cpp | 97 | ||||
-rw-r--r-- | test/ARCMT/Common.h | 6 | ||||
-rw-r--r-- | test/ARCMT/block_copy_release.m | 17 | ||||
-rw-r--r-- | test/ARCMT/block_copy_release.m.result | 15 |
4 files changed, 126 insertions, 9 deletions
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 55518d1266..3c77f2e6b3 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -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 @@ class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{ 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 @@ public: 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 @@ private: 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); diff --git a/test/ARCMT/Common.h b/test/ARCMT/Common.h index ed48949702..b388ecab74 100644 --- a/test/ARCMT/Common.h +++ b/test/ARCMT/Common.h @@ -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 @@ NS_INLINE id CFBridgingRelease(CFTypeRef CF_CONSUMED X) { } #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__)) diff --git a/test/ARCMT/block_copy_release.m b/test/ARCMT/block_copy_release.m new file mode 100644 index 0000000000..ae3b82660a --- /dev/null +++ b/test/ARCMT/block_copy_release.m @@ -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); +} diff --git a/test/ARCMT/block_copy_release.m.result b/test/ARCMT/block_copy_release.m.result new file mode 100644 index 0000000000..b292b64f17 --- /dev/null +++ b/test/ARCMT/block_copy_release.m.result @@ -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]; +} |