[arcmt] Rewrite uses of Block_copy/Block_release macros.
c = Block_copy(b); Block_release(c); ----> c = [b copy]; <removed> rdar://9408211 llvm-svn: 171454
This commit is contained in:
parent
95de3f3018
commit
6ba7afb8e1
|
@ -30,6 +30,14 @@
|
||||||
// ---->
|
// ---->
|
||||||
// CFStringRef str = (__bridge CFStringRef)self;
|
// 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"
|
#include "Transforms.h"
|
||||||
|
@ -54,32 +62,32 @@ class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
|
||||||
IdentifierInfo *SelfII;
|
IdentifierInfo *SelfII;
|
||||||
OwningPtr<ParentMap> StmtMap;
|
OwningPtr<ParentMap> StmtMap;
|
||||||
Decl *ParentD;
|
Decl *ParentD;
|
||||||
|
Stmt *Body;
|
||||||
|
mutable OwningPtr<ExprSet> Removables;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0) {
|
UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0), Body(0) {
|
||||||
SelfII = &Pass.Ctx.Idents.get("self");
|
SelfII = &Pass.Ctx.Idents.get("self");
|
||||||
}
|
}
|
||||||
|
|
||||||
void transformBody(Stmt *body, Decl *ParentD) {
|
void transformBody(Stmt *body, Decl *ParentD) {
|
||||||
this->ParentD = ParentD;
|
this->ParentD = ParentD;
|
||||||
|
Body = body;
|
||||||
StmtMap.reset(new ParentMap(body));
|
StmtMap.reset(new ParentMap(body));
|
||||||
TraverseStmt(body);
|
TraverseStmt(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VisitCastExpr(CastExpr *E) {
|
bool VisitCastExpr(CastExpr *E) {
|
||||||
if (E->getCastKind() != CK_CPointerToObjCPointerCast
|
if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
|
||||||
&& E->getCastKind() != CK_BitCast)
|
E->getCastKind() != CK_BitCast &&
|
||||||
|
E->getCastKind() != CK_AnyPointerToBlockPointerCast)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
QualType castType = E->getType();
|
QualType castType = E->getType();
|
||||||
Expr *castExpr = E->getSubExpr();
|
Expr *castExpr = E->getSubExpr();
|
||||||
QualType castExprType = castExpr->getType();
|
QualType castExprType = castExpr->getType();
|
||||||
|
|
||||||
if (castType->isObjCObjectPointerType() &&
|
if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
|
||||||
castExprType->isObjCObjectPointerType())
|
|
||||||
return true;
|
|
||||||
if (!castType->isObjCObjectPointerType() &&
|
|
||||||
!castExprType->isObjCObjectPointerType())
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
|
bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
|
||||||
|
@ -94,7 +102,7 @@ public:
|
||||||
if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
|
if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (castType->isObjCObjectPointerType())
|
if (castType->isObjCRetainableType())
|
||||||
transformNonObjCToObjCCast(E);
|
transformNonObjCToObjCCast(E);
|
||||||
else
|
else
|
||||||
transformObjCToNonObjCCast(E);
|
transformObjCToNonObjCCast(E);
|
||||||
|
@ -263,7 +271,78 @@ private:
|
||||||
rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
|
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) {
|
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()))
|
if (isSelf(E->getSubExpr()))
|
||||||
return rewriteToBridgedCast(E, OBC_Bridge);
|
return rewriteToBridgedCast(E, OBC_Bridge);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#define NS_INLINE static __inline__ __attribute__((always_inline))
|
#define NS_INLINE static __inline__ __attribute__((always_inline))
|
||||||
#define nil ((void*) 0)
|
#define nil ((void*) 0)
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
typedef unsigned NSUInteger;
|
typedef unsigned NSUInteger;
|
||||||
|
@ -102,3 +103,8 @@ NS_INLINE id CFBridgingRelease(CFTypeRef CF_CONSUMED X) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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__))
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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];
|
||||||
|
}
|
Loading…
Reference in New Issue