TransRetainReleaseDealloc.cpp revision 2c18ca0575b60082f2a9f4563b4071071960d37c
17196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===--- TransRetainReleaseDealloc.cpp - Tranformations 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// removeRetainReleaseDealloc: 117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Removes retain/release/autorelease/dealloc messages. 137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// return [[foo retain] autorelease]; 157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// ----> 167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// return foo; 177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// 187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Transforms.h" 217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "Internals.h" 227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h" 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang; 267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt; 277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing llvm::StringRef; 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace { 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass RetainReleaseDeallocRemover : 337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis public RecursiveASTVisitor<RetainReleaseDeallocRemover> { 347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Stmt *Body; 357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ExprSet Removables; 387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis llvm::OwningPtr<ParentMap> StmtMap; 397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 41b1094a0621c3bf91141f7cd9684ca80b357ae61eArgyrios Kyrtzidis RetainReleaseDeallocRemover(MigrationPass &pass) 42b1094a0621c3bf91141f7cd9684ca80b357ae61eArgyrios Kyrtzidis : Body(0), Pass(pass) { } 437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis void transformBody(Stmt *body) { 457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Body = body; 467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis collectRemovables(body, Removables); 477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis StmtMap.reset(new ParentMap(body)); 487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis TraverseStmt(body); 497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (E->getMethodFamily()) { 537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis default: 547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 55e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis case OMF_autorelease: 56e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis if (isRemovable(E)) { 57e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis // An unused autorelease is badness. If we remove it the receiver 58e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis // will likely die immediately while previously it was kept alive 59e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis // by the autorelease pool. This is bad practice in general, leave it 60e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis // and emit an error to force the user to restructure his code. 61e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis std::string err = "it is not safe to remove an unused '"; 62e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis err += E->getSelector().getAsString() + "'; its receiver may be " 63e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis "destroyed immediately"; 64e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis Pass.TA.reportError(err, E->getLocStart(), E->getSourceRange()); 65e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis return true; 66e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis } 67e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis // Pass through. 687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_retain: 697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_release: 707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (E->getReceiverKind() == ObjCMessageExpr::Instance) 717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (Expr *rec = E->getInstanceReceiver()) { 727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rec = rec->IgnoreParenImpCasts(); 732cd5366ff52b4592776ee4db27012d16fb995c62Argyrios Kyrtzidis if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone && 742cd5366ff52b4592776ee4db27012d16fb995c62Argyrios Kyrtzidis (E->getMethodFamily() != OMF_retain || isRemovable(E))) { 75e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis std::string err = "it is not safe to remove '"; 767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis err += E->getSelector().getAsString() + "' message on " 777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis "an __unsafe_unretained type"; 787196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.reportError(err, rec->getLocStart()); 797196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 807196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 812c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis 822c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis if (isGlobalVar(rec) && 832c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis (E->getMethodFamily() != OMF_retain || isRemovable(E))) { 842c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis std::string err = "it is not safe to remove '"; 852c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis err += E->getSelector().getAsString() + "' message on " 862c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis "a global variable"; 872c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis Pass.TA.reportError(err, rec->getLocStart()); 882c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis return true; 892c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis } 907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_dealloc: 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (E->getReceiverKind()) { 967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis default: 977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case ObjCMessageExpr::SuperInstance: { 997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message, 1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_unavailable, 1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_unavailable_message, 1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis E->getSuperLoc()); 1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tryRemoving(E)) 1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replace(E->getSourceRange(), "self"); 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case ObjCMessageExpr::Instance: 1107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Expr *rec = E->getInstanceReceiver(); 1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!rec) return true; 1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message, 1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_unavailable, 1197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis diag::err_unavailable_message, 1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rec->getExprLoc()); 1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!hasSideEffects(E, Pass.Ctx)) { 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tryRemoving(E)) 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replace(E->getSourceRange(), rec->getSourceRange()); 1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisprivate: 1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool isRemovable(Expr *E) const { 1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return Removables.count(E); 1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool tryRemoving(Expr *E) const { 1367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (isRemovable(E)) { 1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.removeStmt(E); 1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1417e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall Stmt *parent = StmtMap->getParent(E); 1427e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall 1437e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall if (ImplicitCastExpr *castE = dyn_cast_or_null<ImplicitCastExpr>(parent)) 1447e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall return tryRemoving(castE); 1457e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall 1467e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent)) 1477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return tryRemoving(parenE); 1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (BinaryOperator * 1507e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall bopE = dyn_cast_or_null<BinaryOperator>(parent)) { 1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E && 1527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis isRemovable(bopE)) { 1537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange()); 1547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return false; 1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 1627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace 1647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid trans::removeRetainReleaseDealloc(MigrationPass &pass) { 1667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis BodyTransform<RetainReleaseDeallocRemover> trans(pass); 1677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 169