TransRetainReleaseDealloc.cpp 14 KB

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