TransRetainReleaseDealloc.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. //===--- TransRetainReleaseDealloc.cpp - Transformations to ARC mode ------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // removeRetainReleaseDealloc:
  11. //
  12. // Removes retain/release/autorelease/dealloc messages.
  13. //
  14. // return [[foo retain] autorelease];
  15. // ---->
  16. // return foo;
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #include "Transforms.h"
  20. #include "Internals.h"
  21. #include "clang/AST/ASTContext.h"
  22. #include "clang/AST/ParentMap.h"
  23. #include "clang/Basic/SourceManager.h"
  24. #include "clang/Lex/Lexer.h"
  25. #include "clang/Sema/SemaDiagnostic.h"
  26. #include "llvm/ADT/StringSwitch.h"
  27. using namespace clang;
  28. using namespace arcmt;
  29. using namespace trans;
  30. namespace {
  31. class RetainReleaseDeallocRemover :
  32. public RecursiveASTVisitor<RetainReleaseDeallocRemover> {
  33. Stmt *Body;
  34. MigrationPass &Pass;
  35. ExprSet Removables;
  36. std::unique_ptr<ParentMap> StmtMap;
  37. Selector DelegateSel, FinalizeSel;
  38. public:
  39. RetainReleaseDeallocRemover(MigrationPass &pass)
  40. : Body(nullptr), Pass(pass) {
  41. DelegateSel =
  42. Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate"));
  43. FinalizeSel =
  44. Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
  45. }
  46. void transformBody(Stmt *body, Decl *ParentD) {
  47. Body = body;
  48. collectRemovables(body, Removables);
  49. StmtMap.reset(new ParentMap(body));
  50. TraverseStmt(body);
  51. }
  52. bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
  53. switch (E->getMethodFamily()) {
  54. default:
  55. if (E->isInstanceMessage() && E->getSelector() == FinalizeSel)
  56. break;
  57. return true;
  58. case OMF_autorelease:
  59. if (isRemovable(E)) {
  60. if (!isCommonUnusedAutorelease(E)) {
  61. // An unused autorelease is badness. If we remove it the receiver
  62. // will likely die immediately while previously it was kept alive
  63. // by the autorelease pool. This is bad practice in general, leave it
  64. // and emit an error to force the user to restructure their code.
  65. Pass.TA.reportError("it is not safe to remove an unused 'autorelease' "
  66. "message; its receiver may be destroyed immediately",
  67. E->getLocStart(), E->getSourceRange());
  68. return true;
  69. }
  70. }
  71. // Pass through.
  72. case OMF_retain:
  73. case OMF_release:
  74. if (E->getReceiverKind() == ObjCMessageExpr::Instance)
  75. if (Expr *rec = E->getInstanceReceiver()) {
  76. rec = rec->IgnoreParenImpCasts();
  77. if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
  78. (E->getMethodFamily() != OMF_retain || isRemovable(E))) {
  79. std::string err = "it is not safe to remove '";
  80. err += E->getSelector().getAsString() + "' message on "
  81. "an __unsafe_unretained type";
  82. Pass.TA.reportError(err, rec->getLocStart());
  83. return true;
  84. }
  85. if (isGlobalVar(rec) &&
  86. (E->getMethodFamily() != OMF_retain || isRemovable(E))) {
  87. std::string err = "it is not safe to remove '";
  88. err += E->getSelector().getAsString() + "' message on "
  89. "a global variable";
  90. Pass.TA.reportError(err, rec->getLocStart());
  91. return true;
  92. }
  93. if (E->getMethodFamily() == OMF_release && isDelegateMessage(rec)) {
  94. Pass.TA.reportError("it is not safe to remove 'retain' "
  95. "message on the result of a 'delegate' message; "
  96. "the object that was passed to 'setDelegate:' may not be "
  97. "properly retained", rec->getLocStart());
  98. return true;
  99. }
  100. }
  101. case OMF_dealloc:
  102. break;
  103. }
  104. switch (E->getReceiverKind()) {
  105. default:
  106. return true;
  107. case ObjCMessageExpr::SuperInstance: {
  108. Transaction Trans(Pass.TA);
  109. clearDiagnostics(E->getSelectorLoc(0));
  110. if (tryRemoving(E))
  111. return true;
  112. Pass.TA.replace(E->getSourceRange(), "self");
  113. return true;
  114. }
  115. case ObjCMessageExpr::Instance:
  116. break;
  117. }
  118. Expr *rec = E->getInstanceReceiver();
  119. if (!rec) return true;
  120. Transaction Trans(Pass.TA);
  121. clearDiagnostics(E->getSelectorLoc(0));
  122. ObjCMessageExpr *Msg = E;
  123. Expr *RecContainer = Msg;
  124. SourceRange RecRange = rec->getSourceRange();
  125. checkForGCDOrXPC(Msg, RecContainer, rec, RecRange);
  126. if (Msg->getMethodFamily() == OMF_release &&
  127. isRemovable(RecContainer) && isInAtFinally(RecContainer)) {
  128. // Change the -release to "receiver = nil" in a finally to avoid a leak
  129. // when an exception is thrown.
  130. Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
  131. std::string str = " = ";
  132. str += getNilString(Pass);
  133. Pass.TA.insertAfterToken(RecRange.getEnd(), str);
  134. return true;
  135. }
  136. if (!hasSideEffects(rec, Pass.Ctx)) {
  137. if (tryRemoving(RecContainer))
  138. return true;
  139. }
  140. Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
  141. return true;
  142. }
  143. private:
  144. /// \brief Checks for idioms where an unused -autorelease is common.
  145. ///
  146. /// Returns true for this idiom which is common in property
  147. /// setters:
  148. ///
  149. /// [backingValue autorelease];
  150. /// backingValue = [newValue retain]; // in general a +1 assign
  151. ///
  152. /// For these as well:
  153. ///
  154. /// [[var retain] autorelease];
  155. /// return var;
  156. ///
  157. bool isCommonUnusedAutorelease(ObjCMessageExpr *E) {
  158. if (isPlusOneAssignBeforeOrAfterAutorelease(E))
  159. return true;
  160. if (isReturnedAfterAutorelease(E))
  161. return true;
  162. return false;
  163. }
  164. bool isReturnedAfterAutorelease(ObjCMessageExpr *E) {
  165. Expr *Rec = E->getInstanceReceiver();
  166. if (!Rec)
  167. return false;
  168. Decl *RefD = getReferencedDecl(Rec);
  169. if (!RefD)
  170. return false;
  171. Stmt *nextStmt = getNextStmt(E);
  172. if (!nextStmt)
  173. return false;
  174. // Check for "return <variable>;".
  175. if (ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt))
  176. return RefD == getReferencedDecl(RetS->getRetValue());
  177. return false;
  178. }
  179. bool isPlusOneAssignBeforeOrAfterAutorelease(ObjCMessageExpr *E) {
  180. Expr *Rec = E->getInstanceReceiver();
  181. if (!Rec)
  182. return false;
  183. Decl *RefD = getReferencedDecl(Rec);
  184. if (!RefD)
  185. return false;
  186. Stmt *prevStmt, *nextStmt;
  187. std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E);
  188. return isPlusOneAssignToVar(prevStmt, RefD) ||
  189. isPlusOneAssignToVar(nextStmt, RefD);
  190. }
  191. bool isPlusOneAssignToVar(Stmt *S, Decl *RefD) {
  192. if (!S)
  193. return false;
  194. // Check for "RefD = [+1 retained object];".
  195. if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
  196. if (RefD != getReferencedDecl(Bop->getLHS()))
  197. return false;
  198. if (isPlusOneAssign(Bop))
  199. return true;
  200. return false;
  201. }
  202. if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
  203. if (DS->isSingleDecl() && DS->getSingleDecl() == RefD) {
  204. if (VarDecl *VD = dyn_cast<VarDecl>(RefD))
  205. return isPlusOne(VD->getInit());
  206. }
  207. return false;
  208. }
  209. return false;
  210. }
  211. Stmt *getNextStmt(Expr *E) {
  212. return getPreviousAndNextStmt(E).second;
  213. }
  214. std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(Expr *E) {
  215. Stmt *prevStmt = nullptr, *nextStmt = nullptr;
  216. if (!E)
  217. return std::make_pair(prevStmt, nextStmt);
  218. Stmt *OuterS = E, *InnerS;
  219. do {
  220. InnerS = OuterS;
  221. OuterS = StmtMap->getParent(InnerS);
  222. }
  223. while (OuterS && (isa<ParenExpr>(OuterS) ||
  224. isa<CastExpr>(OuterS) ||
  225. isa<ExprWithCleanups>(OuterS)));
  226. if (!OuterS)
  227. return std::make_pair(prevStmt, nextStmt);
  228. Stmt::child_iterator currChildS = OuterS->child_begin();
  229. Stmt::child_iterator childE = OuterS->child_end();
  230. Stmt::child_iterator prevChildS = childE;
  231. for (; currChildS != childE; ++currChildS) {
  232. if (*currChildS == InnerS)
  233. break;
  234. prevChildS = currChildS;
  235. }
  236. if (prevChildS != childE) {
  237. prevStmt = *prevChildS;
  238. if (prevStmt)
  239. prevStmt = prevStmt->IgnoreImplicit();
  240. }
  241. if (currChildS == childE)
  242. return std::make_pair(prevStmt, nextStmt);
  243. ++currChildS;
  244. if (currChildS == childE)
  245. return std::make_pair(prevStmt, nextStmt);
  246. nextStmt = *currChildS;
  247. if (nextStmt)
  248. nextStmt = nextStmt->IgnoreImplicit();
  249. return std::make_pair(prevStmt, nextStmt);
  250. }
  251. Decl *getReferencedDecl(Expr *E) {
  252. if (!E)
  253. return nullptr;
  254. E = E->IgnoreParenCasts();
  255. if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
  256. switch (ME->getMethodFamily()) {
  257. case OMF_copy:
  258. case OMF_autorelease:
  259. case OMF_release:
  260. case OMF_retain:
  261. return getReferencedDecl(ME->getInstanceReceiver());
  262. default:
  263. return nullptr;
  264. }
  265. }
  266. if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
  267. return DRE->getDecl();
  268. if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
  269. return ME->getMemberDecl();
  270. if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(E))
  271. return IRE->getDecl();
  272. return nullptr;
  273. }
  274. /// \brief Check if the retain/release is due to a GCD/XPC macro that are
  275. /// defined as:
  276. ///
  277. /// #define dispatch_retain(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); (void)[_o retain]; })
  278. /// #define dispatch_release(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); [_o release]; })
  279. /// #define xpc_retain(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o retain]; })
  280. /// #define xpc_release(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o release]; })
  281. ///
  282. /// and return the top container which is the StmtExpr and the macro argument
  283. /// expression.
  284. void checkForGCDOrXPC(ObjCMessageExpr *Msg, Expr *&RecContainer,
  285. Expr *&Rec, SourceRange &RecRange) {
  286. SourceLocation Loc = Msg->getExprLoc();
  287. if (!Loc.isMacroID())
  288. return;
  289. SourceManager &SM = Pass.Ctx.getSourceManager();
  290. StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM,
  291. Pass.Ctx.getLangOpts());
  292. bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName)
  293. .Case("dispatch_retain", true)
  294. .Case("dispatch_release", true)
  295. .Case("xpc_retain", true)
  296. .Case("xpc_release", true)
  297. .Default(false);
  298. if (!isGCDOrXPC)
  299. return;
  300. StmtExpr *StmtE = nullptr;
  301. Stmt *S = Msg;
  302. while (S) {
  303. if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
  304. StmtE = SE;
  305. break;
  306. }
  307. S = StmtMap->getParent(S);
  308. }
  309. if (!StmtE)
  310. return;
  311. Stmt::child_range StmtExprChild = StmtE->children();
  312. if (!StmtExprChild)
  313. return;
  314. CompoundStmt *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild);
  315. if (!CompS)
  316. return;
  317. Stmt::child_range CompStmtChild = CompS->children();
  318. if (!CompStmtChild)
  319. return;
  320. DeclStmt *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild);
  321. if (!DeclS)
  322. return;
  323. if (!DeclS->isSingleDecl())
  324. return;
  325. VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl());
  326. if (!VD)
  327. return;
  328. Expr *Init = VD->getInit();
  329. if (!Init)
  330. return;
  331. RecContainer = StmtE;
  332. Rec = Init->IgnoreParenImpCasts();
  333. if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec))
  334. Rec = EWC->getSubExpr()->IgnoreParenImpCasts();
  335. RecRange = Rec->getSourceRange();
  336. if (SM.isMacroArgExpansion(RecRange.getBegin()))
  337. RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
  338. if (SM.isMacroArgExpansion(RecRange.getEnd()))
  339. RecRange.setEnd(SM.getImmediateSpellingLoc(RecRange.getEnd()));
  340. }
  341. void clearDiagnostics(SourceLocation loc) const {
  342. Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
  343. diag::err_unavailable,
  344. diag::err_unavailable_message,
  345. loc);
  346. }
  347. bool isDelegateMessage(Expr *E) const {
  348. if (!E) return false;
  349. E = E->IgnoreParenCasts();
  350. // Also look through property-getter sugar.
  351. if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E))
  352. E = pseudoOp->getResultExpr()->IgnoreImplicit();
  353. if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
  354. return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
  355. return false;
  356. }
  357. bool isInAtFinally(Expr *E) const {
  358. assert(E);
  359. Stmt *S = E;
  360. while (S) {
  361. if (isa<ObjCAtFinallyStmt>(S))
  362. return true;
  363. S = StmtMap->getParent(S);
  364. }
  365. return false;
  366. }
  367. bool isRemovable(Expr *E) const {
  368. return Removables.count(E);
  369. }
  370. bool tryRemoving(Expr *E) const {
  371. if (isRemovable(E)) {
  372. Pass.TA.removeStmt(E);
  373. return true;
  374. }
  375. Stmt *parent = StmtMap->getParent(E);
  376. if (ImplicitCastExpr *castE = dyn_cast_or_null<ImplicitCastExpr>(parent))
  377. return tryRemoving(castE);
  378. if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent))
  379. return tryRemoving(parenE);
  380. if (BinaryOperator *
  381. bopE = dyn_cast_or_null<BinaryOperator>(parent)) {
  382. if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E &&
  383. isRemovable(bopE)) {
  384. Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
  385. return true;
  386. }
  387. }
  388. return false;
  389. }
  390. };
  391. } // anonymous namespace
  392. void trans::removeRetainReleaseDeallocFinalize(MigrationPass &pass) {
  393. BodyTransform<RetainReleaseDeallocRemover> trans(pass);
  394. trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
  395. }