1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===// 27196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 37196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// The LLVM Compiler Infrastructure 47196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 57196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 67196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// License. See LICENSE.TXT for details. 77196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 87196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 97196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// rewriteUnbridgedCasts: 117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer 137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// is from a file-level variable, __bridge cast is used to convert it. 147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// For the result of a function call that we know is +1/+0, 15684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis// __bridge/CFBridgingRelease is used. 167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSString *str = (NSString *)kUTTypePlainText; 187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// str = b ? kUTTypeRTF : kUTTypePlainText; 197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, 207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// _uuid); 217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ----> 227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// NSString *str = (__bridge NSString *)kUTTypePlainText; 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText); 24684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis// NSString *_uuidString = (NSString *) 25684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis// CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid)); 267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// For a C pointer to ObjC, for casting 'self', __bridge is used. 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// CFStringRef str = (CFStringRef)self; 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ----> 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// CFStringRef str = (__bridge CFStringRef)self; 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 335d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// Uses of Block_copy/Block_release macros are rewritten: 345d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// 355d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// c = Block_copy(b); 365d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// Block_release(c); 375d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// ----> 385d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// c = [b copy]; 395d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// <removed> 405d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// 417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h" 447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Internals.h" 45471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 462fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 4718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis#include "clang/AST/ParentMap.h" 482fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Analysis/DomainSpecific/CocoaConventions.h" 497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h" 50471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Lex/Lexer.h" 51471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Sema/SemaDiagnostic.h" 528fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang; 557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt; 567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace { 597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{ 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis IdentifierInfo *SelfII; 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ParentMap> StmtMap; 6476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis Decl *ParentD; 655d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Stmt *Body; 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<ExprSet> Removables; 6718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines UnbridgedCastRewriter(MigrationPass &pass) 706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : Pass(pass), ParentD(nullptr), Body(nullptr) { 717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SelfII = &Pass.Ctx.Idents.get("self"); 727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 7476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis void transformBody(Stmt *body, Decl *ParentD) { 7576a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis this->ParentD = ParentD; 765d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Body = body; 7718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis StmtMap.reset(new ParentMap(body)); 7818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis TraverseStmt(body); 7918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 8018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 8124016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis bool TraverseBlockDecl(BlockDecl *D) { 8224016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis // ParentMap does not enter into a BlockDecl to record its stmts, so use a 8324016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis // new UnbridgedCastRewriter to handle the block. 8424016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D); 8524016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis return true; 8624016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis } 8724016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis 887196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitCastExpr(CastExpr *E) { 895d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (E->getCastKind() != CK_CPointerToObjCPointerCast && 905d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis E->getCastKind() != CK_BitCast && 915d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis E->getCastKind() != CK_AnyPointerToBlockPointerCast) 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis QualType castType = E->getType(); 957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Expr *castExpr = E->getSubExpr(); 967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis QualType castExprType = castExpr->getType(); 977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 985d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType()) 997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool exprRetainable = castExprType->isObjCIndirectLifetimeType(); 1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool castRetainable = castType->isObjCIndirectLifetimeType(); 1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (exprRetainable == castRetainable) return true; 1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (castExpr->isNullPointerConstant(Pass.Ctx, 1067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Expr::NPC_ValueDependentIsNull)) 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis SourceLocation loc = castExpr->getExprLoc(); 1107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc)) 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1135d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (castType->isObjCRetainableType()) 1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis transformNonObjCToObjCCast(E); 1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis else 1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis transformObjCToNonObjCCast(E); 1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisprivate: 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void transformNonObjCToObjCCast(CastExpr *E) { 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!E) return; 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Global vars are assumed that are cast as unretained. 1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (isGlobalVar(E)) 1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (E->getSubExpr()->getType()->isPointerType()) { 1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/false); 1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // If the cast is directly over the result of a Core Foundation function 1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // try to figure out whether it should be cast as retained or unretained. 1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Expr *inner = E->IgnoreParenCasts(); 1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (CallExpr *callE = dyn_cast<CallExpr>(inner)) { 1367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (FunctionDecl *FD = callE->getDirectCallee()) { 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FD->hasAttr<CFReturnsRetainedAttr>()) { 1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/true); 1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FD->hasAttr<CFReturnsNotRetainedAttr>()) { 1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/false); 1437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 1447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (FD->isGlobal() && 1467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis FD->getIdentifier() && 1477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF", 1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis FD->getIdentifier()->getName())) { 1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis StringRef fname = FD->getIdentifier()->getName(); 1507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (fname.endswith("Retain") || 1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis fname.find("Create") != StringRef::npos || 1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis fname.find("Copy") != StringRef::npos) { 1532908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // Do not migrate to couple of bridge transfer casts which 1542908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // cancel each other out. Leave it unchanged so error gets user 1552908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // attention instead. 1562908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian if (FD->getName() == "CFRetain" && 1572908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian FD->getNumParams() == 1 && 1582908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian FD->getParent()->isTranslationUnit() && 159181e3ecc0907ae0103586a9f4db52241995a8267Rafael Espindola FD->isExternallyVisible()) { 1602908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian Expr *Arg = callE->getArg(0); 1619c7aed308aa701e0ba573c04ebe8d17a4c1486c4Fariborz Jahanian if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { 1622908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian const Expr *sub = ICE->getSubExpr(); 1632908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian QualType T = sub->getType(); 1642908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian if (T->isObjCObjectPointerType()) 1652908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian return; 1662908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian } 1672908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian } 1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/true); 1697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (fname.find("Get") != StringRef::npos) { 1737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/false); 1747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 1757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 17976a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis 18076a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis // If returning an ivar or a member of an ivar from a +0 method, use 18176a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis // a __bridge cast. 18276a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis Expr *base = inner->IgnoreParenImpCasts(); 18376a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis while (isa<MemberExpr>(base)) 18476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts(); 18576a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis if (isa<ObjCIvarRefExpr>(base) && 18676a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) { 18776a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) { 18876a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis if (!method->hasAttr<NSReturnsRetainedAttr>()) { 18976a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis castToObjCObject(E, /*retained=*/false); 19076a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis return; 19176a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis } 19276a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis } 19376a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis } 1947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void castToObjCObject(CastExpr *E, bool retained) { 1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge); 1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) { 20118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Transaction Trans(Pass.TA); 20218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis rewriteToBridgedCast(E, Kind, Trans); 20318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 20418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind, 20618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Transaction &Trans) { 2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis TransformActions &TA = Pass.TA; 2087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // We will remove the compiler diagnostic. 2107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast, 2117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_arc_cast_requires_bridge, 21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis E->getLocStart())) { 21318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Trans.abort(); 2147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return; 21518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis StringRef bridge; 2187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch(Kind) { 2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OBC_Bridge: 2207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bridge = "__bridge "; break; 2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OBC_BridgeTransfer: 2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bridge = "__bridge_transfer "; break; 2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OBC_BridgeRetained: 2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bridge = "__bridge_retained "; break; 2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis TA.clearDiagnostic(diag::err_arc_mismatched_cast, 2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_arc_cast_requires_bridge, 2297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis E->getLocStart()); 230684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) { 231684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) { 232684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis TA.insertAfterToken(CCE->getLParenLoc(), bridge); 2337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } else { 234684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis SourceLocation insertLoc = E->getSubExpr()->getLocStart(); 235684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis SmallString<128> newCast; 2367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis newCast += '('; 237684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis newCast += bridge; 238684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); 239684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis newCast += ')'; 240684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 241684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis if (isa<ParenExpr>(E->getSubExpr())) { 242684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis TA.insert(insertLoc, newCast.str()); 243684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } else { 244684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis newCast += '('; 245684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis TA.insert(insertLoc, newCast.str()); 246684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis TA.insertAfterToken(E->getLocEnd(), ")"); 247684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } 248684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } 249684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } else { 250684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained); 251d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose SmallString<32> BridgeCall; 252d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose 253d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose Expr *WrapE = E->getSubExpr(); 254d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose SourceLocation InsertLoc = WrapE->getLocStart(); 255d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose 256d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose SourceManager &SM = Pass.Ctx.getSourceManager(); 257d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1)); 258d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts())) 259d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose BridgeCall += ' '; 260d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose 261684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis if (Kind == OBC_BridgeTransfer) 262d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose BridgeCall += "CFBridgingRelease"; 263684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis else 264d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose BridgeCall += "CFBridgingRetain"; 265684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 266684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis if (isa<ParenExpr>(WrapE)) { 267d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose TA.insert(InsertLoc, BridgeCall); 268684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } else { 269d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose BridgeCall += '('; 270d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose TA.insert(InsertLoc, BridgeCall); 271684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis TA.insertAfterToken(WrapE->getLocEnd(), ")"); 2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 27618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) { 27718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Transaction Trans(Pass.TA); 27818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange()); 27918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans); 28018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 28118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 2825d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) { 2835d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceManager &SM = Pass.Ctx.getSourceManager(); 2845d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceLocation Loc = E->getExprLoc(); 2855d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis assert(Loc.isMacroID()); 2865d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceLocation MacroBegin, MacroEnd; 287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc); 2885d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange(); 2895d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin()); 2905d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd()); 2915d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 2925d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Outer = SourceRange(MacroBegin, MacroEnd); 2935d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Inner = SourceRange(InnerBegin, InnerEnd); 2945d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 2955d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 2965d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis void rewriteBlockCopyMacro(CastExpr *E) { 2975d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceRange OuterRange, InnerRange; 2985d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis getBlockMacroRanges(E, OuterRange, InnerRange); 2995d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3005d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Transaction Trans(Pass.TA); 3015d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.replace(OuterRange, InnerRange); 3025d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.insert(InnerRange.getBegin(), "["); 3035d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]"); 3045d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast, 3055d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis diag::err_arc_cast_requires_bridge, 3065d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis OuterRange); 3075d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3085d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3095d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis void removeBlockReleaseMacro(CastExpr *E) { 3105d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceRange OuterRange, InnerRange; 3115d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis getBlockMacroRanges(E, OuterRange, InnerRange); 3125d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3135d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Transaction Trans(Pass.TA); 3145d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast, 3155d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis diag::err_arc_cast_requires_bridge, 3165d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis OuterRange); 3175d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (!hasSideEffects(E, Pass.Ctx)) { 3185d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E)))) 3195d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return; 3205d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3215d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.replace(OuterRange, InnerRange); 3225d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3235d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3245d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis bool tryRemoving(Expr *E) const { 3255d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (!Removables) { 3265d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Removables.reset(new ExprSet); 3275d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis collectRemovables(Body, *Removables); 3285d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3295d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3305d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (Removables->count(E)) { 3315d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.TA.removeStmt(E); 3325d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return true; 3335d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3345d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3355d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return false; 3365d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3375d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void transformObjCToNonObjCCast(CastExpr *E) { 3395d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis SourceLocation CastLoc = E->getExprLoc(); 3405d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (CastLoc.isMacroID()) { 3415d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis StringRef MacroName = Lexer::getImmediateMacroName(CastLoc, 3425d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.Ctx.getSourceManager(), 3435d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis Pass.Ctx.getLangOpts()); 3445d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (MacroName == "Block_copy") { 3455d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis rewriteBlockCopyMacro(E); 3465d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return; 3475d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3485d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (MacroName == "Block_release") { 3495d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis removeBlockReleaseMacro(E); 3505d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return; 3515d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3525d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3535d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (isSelf(E->getSubExpr())) 3557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return rewriteToBridgedCast(E, OBC_Bridge); 35618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 35718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis CallExpr *callE; 35818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (isPassedToCFRetain(E, callE)) 35918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return rewriteCastForCFRetain(E, callE); 36018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 36118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr()); 36218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (family == OMF_retain) 36318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return rewriteToBridgedCast(E, OBC_BridgeRetained); 36418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 36518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (family == OMF_autorelease || family == OMF_release) { 36618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis std::string err = "it is not safe to cast to '"; 36730c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); 36818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis err += "' the result of '"; 36918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis err += family == OMF_autorelease ? "autorelease" : "release"; 37018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis err += "' message; a __bridge cast may result in a pointer to a " 37118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis "destroyed object and a __bridge_retained may leak the object"; 37218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.reportError(err, E->getLocStart(), 37318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis E->getSubExpr()->getSourceRange()); 37418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Stmt *parent = E; 37518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis do { 37618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis parent = StmtMap->getParentIgnoreParenImpCasts(parent); 37718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } while (parent && isa<ExprWithCleanups>(parent)); 37818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 37918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) { 38018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis std::string note = "remove the cast and change return type of function " 38118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis "to '"; 38230c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy()); 38318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis note += "' to have the object automatically autoreleased"; 38418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.reportNote(note, retS->getLocStart()); 38518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 38618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 38718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *subExpr = E->getSubExpr(); 3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3904b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Look through pseudo-object expressions. 3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) { 3924b9c2d235fb9449e249d74f48ecfec601650de93John McCall subExpr = pseudo->getResultExpr(); 3934b9c2d235fb9449e249d74f48ecfec601650de93John McCall assert(subExpr && "no result for pseudo-object of non-void type?"); 3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall 3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) { 39733e56f3273457bfa22c7c50bc46cf5a18216863dJohn McCall if (implCE->getCastKind() == CK_ARCConsumeObject) 39818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return rewriteToBridgedCast(E, OBC_BridgeRetained); 39933e56f3273457bfa22c7c50bc46cf5a18216863dJohn McCall if (implCE->getCastKind() == CK_ARCReclaimReturnedObject) 40018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return rewriteToBridgedCast(E, OBC_Bridge); 40118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 4024532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis 4034532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis bool isConsumed = false; 4044532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis if (isPassedToCParamWithKnownOwnership(E, isConsumed)) 4054532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained 4064532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis : OBC_Bridge); 40718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 40818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 40918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis static ObjCMethodFamily getFamilyOfMessage(Expr *E) { 41018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis E = E->IgnoreParenCasts(); 41118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) 41218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return ME->getMethodFamily(); 41318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 41418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return OMF_None; 41518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 41618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 41718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const { 41818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if ((callE = dyn_cast_or_null<CallExpr>( 41918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis StmtMap->getParentIgnoreParenImpCasts(E)))) 42018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (FunctionDecl * 42118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) 42218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 && 42318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis FD->getParent()->isTranslationUnit() && 424181e3ecc0907ae0103586a9f4db52241995a8267Rafael Espindola FD->isExternallyVisible()) 42518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return true; 42618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 42718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return false; 4287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4304532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const { 4314532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis if (CallExpr *callE = dyn_cast_or_null<CallExpr>( 4324532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis StmtMap->getParentIgnoreParenImpCasts(E))) 4334532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis if (FunctionDecl * 4344532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) { 4354532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis unsigned i = 0; 4364532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis for (unsigned e = callE->getNumArgs(); i != e; ++i) { 4374532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis Expr *arg = callE->getArg(i); 4384532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis if (arg == E || arg->IgnoreParenImpCasts() == E) 4394532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis break; 4404532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis } 44133ace0669393acb84c24a7ff7a80e8759777b3e8Argyrios Kyrtzidis if (i < callE->getNumArgs() && i < FD->getNumParams()) { 4424532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis ParmVarDecl *PD = FD->getParamDecl(i); 443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (PD->hasAttr<CFConsumedAttr>()) { 4444532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis isConsumed = true; 4454532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis return true; 4464532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis } 4474532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis } 4484532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis } 4494532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis 4504532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis return false; 4514532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis } 4524532b5553db699d5bed250454f9a45e0f66f4bf8Argyrios Kyrtzidis 45318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis bool isSelf(Expr *E) const { 4547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis E = E->IgnoreParenLValueCasts(); 4557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) 45618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) 45718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (IPD->getIdentifier() == SelfII) 45818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return true; 45918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 4607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return false; 4617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 4637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // end anonymous namespace 4657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::rewriteUnbridgedCasts(MigrationPass &pass) { 46718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis BodyTransform<UnbridgedCastRewriter> trans(pass); 4687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 4697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 470