1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransRetainReleaseDealloc.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// 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" 22471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 2430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Basic/SourceManager.h" 25471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Lex/Lexer.h" 26471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Sema/SemaDiagnostic.h" 279852f58f50b4fc20914fbce5b4454135a42343f4Benjamin Kramer#include "llvm/ADT/StringSwitch.h" 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace clang; 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace arcmt; 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisusing namespace trans; 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace { 347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisclass RetainReleaseDeallocRemover : 367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis public RecursiveASTVisitor<RetainReleaseDeallocRemover> { 377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Stmt *Body; 387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis MigrationPass &Pass; 397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 407196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis ExprSet Removables; 41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ParentMap> StmtMap; 427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 43e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis Selector DelegateSel, FinalizeSel; 4482a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis 457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidispublic: 46b1094a0621c3bf91141f7cd9684ca80b357ae61eArgyrios Kyrtzidis RetainReleaseDeallocRemover(MigrationPass &pass) 476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : Body(nullptr), Pass(pass) { 4882a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis DelegateSel = 4982a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate")); 50e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis FinalizeSel = 51e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize")); 5282a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis } 537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 5476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis void transformBody(Stmt *body, Decl *ParentD) { 557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Body = body; 567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis collectRemovables(body, Removables); 577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis StmtMap.reset(new ParentMap(body)); 587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis TraverseStmt(body); 597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (E->getMethodFamily()) { 637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis default: 64e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis if (E->isInstanceMessage() && E->getSelector() == FinalizeSel) 65e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis break; 667196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 67e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis case OMF_autorelease: 685a42a0292ad4d11ccf0ae9d06f6c15c3c811adfdArgyrios Kyrtzidis if (isRemovable(E)) { 691b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (!isCommonUnusedAutorelease(E)) { 701b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis // An unused autorelease is badness. If we remove it the receiver 711b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis // will likely die immediately while previously it was kept alive 721b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis // by the autorelease pool. This is bad practice in general, leave it 736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // and emit an error to force the user to restructure their code. 741b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Pass.TA.reportError("it is not safe to remove an unused 'autorelease' " 751b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis "message; its receiver may be destroyed immediately", 761b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis E->getLocStart(), E->getSourceRange()); 771b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return true; 781b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis } 795a42a0292ad4d11ccf0ae9d06f6c15c3c811adfdArgyrios Kyrtzidis } 805a42a0292ad4d11ccf0ae9d06f6c15c3c811adfdArgyrios Kyrtzidis // Pass through. 817196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_retain: 827196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_release: 837196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (E->getReceiverKind() == ObjCMessageExpr::Instance) 847196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (Expr *rec = E->getInstanceReceiver()) { 857196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis rec = rec->IgnoreParenImpCasts(); 862cd5366ff52b4592776ee4db27012d16fb995c62Argyrios Kyrtzidis if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone && 872cd5366ff52b4592776ee4db27012d16fb995c62Argyrios Kyrtzidis (E->getMethodFamily() != OMF_retain || isRemovable(E))) { 88e0e40768cc8c4b2a9093dac3d777e0d362cb7a88Argyrios Kyrtzidis std::string err = "it is not safe to remove '"; 897196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis err += E->getSelector().getAsString() + "' message on " 907196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis "an __unsafe_unretained type"; 917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.reportError(err, rec->getLocStart()); 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 942c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis 952c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis if (isGlobalVar(rec) && 962c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis (E->getMethodFamily() != OMF_retain || isRemovable(E))) { 972c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis std::string err = "it is not safe to remove '"; 982c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis err += E->getSelector().getAsString() + "' message on " 992c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis "a global variable"; 1002c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis Pass.TA.reportError(err, rec->getLocStart()); 1012c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis return true; 1022c18ca0575b60082f2a9f4563b4071071960d37cArgyrios Kyrtzidis } 10382a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis 10482a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis if (E->getMethodFamily() == OMF_release && isDelegateMessage(rec)) { 10582a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis Pass.TA.reportError("it is not safe to remove 'retain' " 10682a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis "message on the result of a 'delegate' message; " 10782a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis "the object that was passed to 'setDelegate:' may not be " 10882a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis "properly retained", rec->getLocStart()); 10982a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis return true; 11082a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis } 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case OMF_dealloc: 1137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (E->getReceiverKind()) { 1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis default: 1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case ObjCMessageExpr::SuperInstance: { 1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 121f4d02398936c0fdc9fe981348519fbc323f24ad0Argyrios Kyrtzidis clearDiagnostics(E->getSelectorLoc(0)); 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (tryRemoving(E)) 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replace(E->getSourceRange(), "self"); 1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case ObjCMessageExpr::Instance: 1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Expr *rec = E->getInstanceReceiver(); 1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (!rec) return true; 1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Transaction Trans(Pass.TA); 135f4d02398936c0fdc9fe981348519fbc323f24ad0Argyrios Kyrtzidis clearDiagnostics(E->getSelectorLoc(0)); 136f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMessageExpr *Msg = E; 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Expr *RecContainer = Msg; 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceRange RecRange = rec->getSourceRange(); 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek checkForGCDOrXPC(Msg, RecContainer, rec, RecRange); 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Msg->getMethodFamily() == OMF_release && 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek isRemovable(RecContainer) && isInAtFinally(RecContainer)) { 1441aa60ff0ad1fb5bcb3042670dfdd7d5a8359d922Argyrios Kyrtzidis // Change the -release to "receiver = nil" in a finally to avoid a leak 145f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis // when an exception is thrown. 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Pass.TA.replace(RecContainer->getSourceRange(), RecRange); 14718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis std::string str = " = "; 14818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis str += getNilString(Pass.Ctx); 14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Pass.TA.insertAfterToken(RecRange.getEnd(), str); 150f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis return true; 151f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis } 152f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!hasSideEffects(rec, Pass.Ctx)) { 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (tryRemoving(RecContainer)) 1557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Pass.TA.replace(RecContainer->getSourceRange(), RecRange); 1587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 1607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 1617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisprivate: 1631b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// \brief Checks for idioms where an unused -autorelease is common. 1641b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// 165af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// Returns true for this idiom which is common in property 1661b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// setters: 1671b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// 1681b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// [backingValue autorelease]; 1691b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// backingValue = [newValue retain]; // in general a +1 assign 1701b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis /// 171af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// For these as well: 172af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// 173af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// [[var retain] autorelease]; 174af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// return var; 175af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis /// 1761b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis bool isCommonUnusedAutorelease(ObjCMessageExpr *E) { 17720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (isPlusOneAssignBeforeOrAfterAutorelease(E)) 178af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return true; 179af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (isReturnedAfterAutorelease(E)) 180af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return true; 181af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 182af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 183af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 184af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis bool isReturnedAfterAutorelease(ObjCMessageExpr *E) { 1851b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Expr *Rec = E->getInstanceReceiver(); 1861b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (!Rec) 1871b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return false; 1881b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 1891b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Decl *RefD = getReferencedDecl(Rec); 1901b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (!RefD) 1911b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return false; 1921b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 193af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis Stmt *nextStmt = getNextStmt(E); 194af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (!nextStmt) 195af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 196af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 197af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis // Check for "return <variable>;". 198af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 199af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt)) 200af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return RefD == getReferencedDecl(RetS->getRetValue()); 201af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 202af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 203af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 204af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 20520bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis bool isPlusOneAssignBeforeOrAfterAutorelease(ObjCMessageExpr *E) { 206af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis Expr *Rec = E->getInstanceReceiver(); 207af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (!Rec) 208af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 209af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 210af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis Decl *RefD = getReferencedDecl(Rec); 211af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (!RefD) 212af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 213af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 21420bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis Stmt *prevStmt, *nextStmt; 215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E); 21620bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 21720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return isPlusOneAssignToVar(prevStmt, RefD) || 21820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis isPlusOneAssignToVar(nextStmt, RefD); 21920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis } 22020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 22120bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis bool isPlusOneAssignToVar(Stmt *S, Decl *RefD) { 22220bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (!S) 223af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 224af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 225af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis // Check for "RefD = [+1 retained object];". 226af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 22720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { 228af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (RefD != getReferencedDecl(Bop->getLHS())) 229af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 230af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (isPlusOneAssign(Bop)) 231af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return true; 23220bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return false; 233af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 23420bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 23520bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 23620bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (DS->isSingleDecl() && DS->getSingleDecl() == RefD) { 23720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (VarDecl *VD = dyn_cast<VarDecl>(RefD)) 23820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return isPlusOne(VD->getInit()); 23920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis } 24020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return false; 24120bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis } 24220bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 243af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return false; 244af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 245af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 246af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis Stmt *getNextStmt(Expr *E) { 24720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return getPreviousAndNextStmt(E).second; 24820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis } 24920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 25020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(Expr *E) { 2516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Stmt *prevStmt = nullptr, *nextStmt = nullptr; 252af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (!E) 25320bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return std::make_pair(prevStmt, nextStmt); 254af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis 2551b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Stmt *OuterS = E, *InnerS; 2561b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis do { 2571b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis InnerS = OuterS; 2581b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis OuterS = StmtMap->getParent(InnerS); 2591b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis } 2601b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis while (OuterS && (isa<ParenExpr>(OuterS) || 2611b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis isa<CastExpr>(OuterS) || 2621b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis isa<ExprWithCleanups>(OuterS))); 2631b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 2641b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (!OuterS) 26520bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return std::make_pair(prevStmt, nextStmt); 2661b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 2671b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Stmt::child_iterator currChildS = OuterS->child_begin(); 2681b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Stmt::child_iterator childE = OuterS->child_end(); 26920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis Stmt::child_iterator prevChildS = childE; 2701b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis for (; currChildS != childE; ++currChildS) { 2711b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (*currChildS == InnerS) 2721b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis break; 27320bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis prevChildS = currChildS; 2741b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis } 27520bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 27620bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (prevChildS != childE) { 27720bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis prevStmt = *prevChildS; 27820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (prevStmt) 27920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis prevStmt = prevStmt->IgnoreImplicit(); 28020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis } 28120bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 2821b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (currChildS == childE) 28320bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return std::make_pair(prevStmt, nextStmt); 2841b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis ++currChildS; 2851b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (currChildS == childE) 28620bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return std::make_pair(prevStmt, nextStmt); 2871b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 28820bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis nextStmt = *currChildS; 28920bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis if (nextStmt) 29020bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis nextStmt = nextStmt->IgnoreImplicit(); 29120bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis 29220bcd4ead46e3764a5d1279845f8ed351f4d3984Argyrios Kyrtzidis return std::make_pair(prevStmt, nextStmt); 2931b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis } 2941b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 2951b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis Decl *getReferencedDecl(Expr *E) { 2961b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (!E) 2976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2981b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 2991b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis E = E->IgnoreParenCasts(); 300af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { 301af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis switch (ME->getMethodFamily()) { 302af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis case OMF_copy: 303af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis case OMF_autorelease: 304af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis case OMF_release: 305af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis case OMF_retain: 306af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis return getReferencedDecl(ME->getInstanceReceiver()); 307af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis default: 3086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 309af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 310af1c08f216cf1ed541d9f502f6c8944d5fd4320cArgyrios Kyrtzidis } 3111b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) 3121b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return DRE->getDecl(); 3131b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) 3141b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return ME->getMemberDecl(); 3151b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(E)) 3161b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis return IRE->getDecl(); 3171b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 3186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3191b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis } 3201b8fbd3601e009803565e74d2ec54abecb5cbf73Argyrios Kyrtzidis 32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// \brief Check if the retain/release is due to a GCD/XPC macro that are 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// defined as: 32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// #define dispatch_retain(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); (void)[_o retain]; }) 32530660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// #define dispatch_release(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); [_o release]; }) 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// #define xpc_retain(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o retain]; }) 32730660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// #define xpc_release(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o release]; }) 32830660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// 32930660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// and return the top container which is the StmtExpr and the macro argument 33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek /// expression. 33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek void checkForGCDOrXPC(ObjCMessageExpr *Msg, Expr *&RecContainer, 33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Expr *&Rec, SourceRange &RecRange) { 33330660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = Msg->getExprLoc(); 33430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!Loc.isMacroID()) 33530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 33630660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceManager &SM = Pass.Ctx.getSourceManager(); 33730660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, 3384e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Pass.Ctx.getLangOpts()); 33930660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName) 34030660a898545416f0fea2d717f16f75640001e38Ted Kremenek .Case("dispatch_retain", true) 34130660a898545416f0fea2d717f16f75640001e38Ted Kremenek .Case("dispatch_release", true) 34230660a898545416f0fea2d717f16f75640001e38Ted Kremenek .Case("xpc_retain", true) 34330660a898545416f0fea2d717f16f75640001e38Ted Kremenek .Case("xpc_release", true) 34430660a898545416f0fea2d717f16f75640001e38Ted Kremenek .Default(false); 34530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!isGCDOrXPC) 34630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 34730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StmtExpr *StmtE = nullptr; 34930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Stmt *S = Msg; 35030660a898545416f0fea2d717f16f75640001e38Ted Kremenek while (S) { 35130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 35230660a898545416f0fea2d717f16f75640001e38Ted Kremenek StmtE = SE; 35330660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 35430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 35530660a898545416f0fea2d717f16f75640001e38Ted Kremenek S = StmtMap->getParent(S); 35630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 35730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 35830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!StmtE) 35930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 36030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 36130660a898545416f0fea2d717f16f75640001e38Ted Kremenek Stmt::child_range StmtExprChild = StmtE->children(); 36230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!StmtExprChild) 36330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 36430660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompoundStmt *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild); 36530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!CompS) 36630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 36730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 36830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Stmt::child_range CompStmtChild = CompS->children(); 36930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!CompStmtChild) 37030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 37130660a898545416f0fea2d717f16f75640001e38Ted Kremenek DeclStmt *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild); 37230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!DeclS) 37330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 37430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!DeclS->isSingleDecl()) 37530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 37630660a898545416f0fea2d717f16f75640001e38Ted Kremenek VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()); 37730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!VD) 37830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 37930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Expr *Init = VD->getInit(); 38030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!Init) 38130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 38230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 38330660a898545416f0fea2d717f16f75640001e38Ted Kremenek RecContainer = StmtE; 38430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rec = Init->IgnoreParenImpCasts(); 38530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec)) 38630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rec = EWC->getSubExpr()->IgnoreParenImpCasts(); 38730660a898545416f0fea2d717f16f75640001e38Ted Kremenek RecRange = Rec->getSourceRange(); 38830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (SM.isMacroArgExpansion(RecRange.getBegin())) 38930660a898545416f0fea2d717f16f75640001e38Ted Kremenek RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin())); 39030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (SM.isMacroArgExpansion(RecRange.getEnd())) 39130660a898545416f0fea2d717f16f75640001e38Ted Kremenek RecRange.setEnd(SM.getImmediateSpellingLoc(RecRange.getEnd())); 39230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 39330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 394f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis void clearDiagnostics(SourceLocation loc) const { 395f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message, 396f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis diag::err_unavailable, 397f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis diag::err_unavailable_message, 398f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis loc); 399f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis } 400f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis 40182a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis bool isDelegateMessage(Expr *E) const { 40282a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis if (!E) return false; 40382a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis 40482a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis E = E->IgnoreParenCasts(); 4054b9c2d235fb9449e249d74f48ecfec601650de93John McCall 4064b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Also look through property-getter sugar. 4074b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E)) 4084b9c2d235fb9449e249d74f48ecfec601650de93John McCall E = pseudoOp->getResultExpr()->IgnoreImplicit(); 4094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 41082a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) 41182a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel); 41282a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis 41382a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis return false; 41482a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis } 41582a921a1a4811f2d6411bcafcb2b7d59a4dd9080Argyrios Kyrtzidis 416f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis bool isInAtFinally(Expr *E) const { 417f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis assert(E); 418f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis Stmt *S = E; 419f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis while (S) { 420f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis if (isa<ObjCAtFinallyStmt>(S)) 421f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis return true; 422f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis S = StmtMap->getParent(S); 423f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis } 424f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis 425f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis return false; 426f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis } 427f55a869ba4c651943715d13d9b9c50a2e752a6acArgyrios Kyrtzidis 4287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool isRemovable(Expr *E) const { 4297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return Removables.count(E); 4307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis bool tryRemoving(Expr *E) const { 4337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (isRemovable(E)) { 4347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.removeStmt(E); 4357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 4367196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4387e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall Stmt *parent = StmtMap->getParent(E); 4397e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall 4407e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall if (ImplicitCastExpr *castE = dyn_cast_or_null<ImplicitCastExpr>(parent)) 4417e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall return tryRemoving(castE); 4427e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall 4437e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent)) 4447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return tryRemoving(parenE); 4457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (BinaryOperator * 4477e5e5f4cc36fe50f46ad76dca7a266434c94f475John McCall bopE = dyn_cast_or_null<BinaryOperator>(parent)) { 4487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E && 4497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis isRemovable(bopE)) { 4507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange()); 4517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return true; 4527196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return false; 4567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 4577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis}; 4597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 4607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} // anonymous namespace 4617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 462e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidisvoid trans::removeRetainReleaseDeallocFinalize(MigrationPass &pass) { 4637196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis BodyTransform<RetainReleaseDeallocRemover> trans(pass); 4647196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 4657196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 466