aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-01-03 03:17:17 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-01-03 03:17:17 +0000
commit5d2faa41bc63a2a29535ae3dbbc99daabf14ea2f (patch)
tree29e76dc61bf421354bccb9e21a4a2d80129992d7 /lib
parentbcde478a5f2600718a225eade94549c9792166b8 (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
Diffstat (limited to 'lib')
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp97
1 files changed, 88 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);