Transforms.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. //===--- Transforms.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. #include "Transforms.h"
  9. #include "Internals.h"
  10. #include "clang/AST/ASTContext.h"
  11. #include "clang/AST/RecursiveASTVisitor.h"
  12. #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
  13. #include "clang/Basic/SourceManager.h"
  14. #include "clang/Basic/TargetInfo.h"
  15. #include "clang/Lex/Lexer.h"
  16. #include "clang/Lex/Preprocessor.h"
  17. #include "clang/Sema/Sema.h"
  18. using namespace clang;
  19. using namespace arcmt;
  20. using namespace trans;
  21. ASTTraverser::~ASTTraverser() { }
  22. bool MigrationPass::CFBridgingFunctionsDefined() {
  23. if (!EnableCFBridgeFns.hasValue())
  24. EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") &&
  25. SemaRef.isKnownName("CFBridgingRelease");
  26. return *EnableCFBridgeFns;
  27. }
  28. //===----------------------------------------------------------------------===//
  29. // Helpers.
  30. //===----------------------------------------------------------------------===//
  31. bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
  32. bool AllowOnUnknownClass) {
  33. if (!Ctx.getLangOpts().ObjCWeakRuntime)
  34. return false;
  35. QualType T = type;
  36. if (T.isNull())
  37. return false;
  38. // iOS is always safe to use 'weak'.
  39. if (Ctx.getTargetInfo().getTriple().isiOS() ||
  40. Ctx.getTargetInfo().getTriple().isWatchOS())
  41. AllowOnUnknownClass = true;
  42. while (const PointerType *ptr = T->getAs<PointerType>())
  43. T = ptr->getPointeeType();
  44. if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
  45. ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
  46. if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
  47. return false; // id/NSObject is not safe for weak.
  48. if (!AllowOnUnknownClass && !Class->hasDefinition())
  49. return false; // forward classes are not verifiable, therefore not safe.
  50. if (Class && Class->isArcWeakrefUnavailable())
  51. return false;
  52. }
  53. return true;
  54. }
  55. bool trans::isPlusOneAssign(const BinaryOperator *E) {
  56. if (E->getOpcode() != BO_Assign)
  57. return false;
  58. return isPlusOne(E->getRHS());
  59. }
  60. bool trans::isPlusOne(const Expr *E) {
  61. if (!E)
  62. return false;
  63. if (const FullExpr *FE = dyn_cast<FullExpr>(E))
  64. E = FE->getSubExpr();
  65. if (const ObjCMessageExpr *
  66. ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
  67. if (ME->getMethodFamily() == OMF_retain)
  68. return true;
  69. if (const CallExpr *
  70. callE = dyn_cast<CallExpr>(E->IgnoreParenCasts())) {
  71. if (const FunctionDecl *FD = callE->getDirectCallee()) {
  72. if (FD->hasAttr<CFReturnsRetainedAttr>())
  73. return true;
  74. if (FD->isGlobal() &&
  75. FD->getIdentifier() &&
  76. FD->getParent()->isTranslationUnit() &&
  77. FD->isExternallyVisible() &&
  78. ento::cocoa::isRefType(callE->getType(), "CF",
  79. FD->getIdentifier()->getName())) {
  80. StringRef fname = FD->getIdentifier()->getName();
  81. if (fname.endswith("Retain") ||
  82. fname.find("Create") != StringRef::npos ||
  83. fname.find("Copy") != StringRef::npos) {
  84. return true;
  85. }
  86. }
  87. }
  88. }
  89. const ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E);
  90. while (implCE && implCE->getCastKind() == CK_BitCast)
  91. implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
  92. return implCE && implCE->getCastKind() == CK_ARCConsumeObject;
  93. }
  94. /// 'Loc' is the end of a statement range. This returns the location
  95. /// immediately after the semicolon following the statement.
  96. /// If no semicolon is found or the location is inside a macro, the returned
  97. /// source location will be invalid.
  98. SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
  99. ASTContext &Ctx, bool IsDecl) {
  100. SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx, IsDecl);
  101. if (SemiLoc.isInvalid())
  102. return SourceLocation();
  103. return SemiLoc.getLocWithOffset(1);
  104. }
  105. /// \arg Loc is the end of a statement range. This returns the location
  106. /// of the semicolon following the statement.
  107. /// If no semicolon is found or the location is inside a macro, the returned
  108. /// source location will be invalid.
  109. SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
  110. ASTContext &Ctx,
  111. bool IsDecl) {
  112. SourceManager &SM = Ctx.getSourceManager();
  113. if (loc.isMacroID()) {
  114. if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc))
  115. return SourceLocation();
  116. }
  117. loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());
  118. // Break down the source location.
  119. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
  120. // Try to load the file buffer.
  121. bool invalidTemp = false;
  122. StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  123. if (invalidTemp)
  124. return SourceLocation();
  125. const char *tokenBegin = file.data() + locInfo.second;
  126. // Lex from the start of the given location.
  127. Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
  128. Ctx.getLangOpts(),
  129. file.begin(), tokenBegin, file.end());
  130. Token tok;
  131. lexer.LexFromRawLexer(tok);
  132. if (tok.isNot(tok::semi)) {
  133. if (!IsDecl)
  134. return SourceLocation();
  135. // Declaration may be followed with other tokens; such as an __attribute,
  136. // before ending with a semicolon.
  137. return findSemiAfterLocation(tok.getLocation(), Ctx, /*IsDecl*/true);
  138. }
  139. return tok.getLocation();
  140. }
  141. bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
  142. if (!E || !E->HasSideEffects(Ctx))
  143. return false;
  144. E = E->IgnoreParenCasts();
  145. ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
  146. if (!ME)
  147. return true;
  148. switch (ME->getMethodFamily()) {
  149. case OMF_autorelease:
  150. case OMF_dealloc:
  151. case OMF_release:
  152. case OMF_retain:
  153. switch (ME->getReceiverKind()) {
  154. case ObjCMessageExpr::SuperInstance:
  155. return false;
  156. case ObjCMessageExpr::Instance:
  157. return hasSideEffects(ME->getInstanceReceiver(), Ctx);
  158. default:
  159. break;
  160. }
  161. break;
  162. default:
  163. break;
  164. }
  165. return true;
  166. }
  167. bool trans::isGlobalVar(Expr *E) {
  168. E = E->IgnoreParenCasts();
  169. if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
  170. return DRE->getDecl()->getDeclContext()->isFileContext() &&
  171. DRE->getDecl()->isExternallyVisible();
  172. if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
  173. return isGlobalVar(condOp->getTrueExpr()) &&
  174. isGlobalVar(condOp->getFalseExpr());
  175. return false;
  176. }
  177. StringRef trans::getNilString(MigrationPass &Pass) {
  178. return Pass.SemaRef.PP.isMacroDefined("nil") ? "nil" : "0";
  179. }
  180. namespace {
  181. class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
  182. ExprSet &Refs;
  183. public:
  184. ReferenceClear(ExprSet &refs) : Refs(refs) { }
  185. bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
  186. };
  187. class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
  188. ValueDecl *Dcl;
  189. ExprSet &Refs;
  190. public:
  191. ReferenceCollector(ValueDecl *D, ExprSet &refs)
  192. : Dcl(D), Refs(refs) { }
  193. bool VisitDeclRefExpr(DeclRefExpr *E) {
  194. if (E->getDecl() == Dcl)
  195. Refs.insert(E);
  196. return true;
  197. }
  198. };
  199. class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
  200. ExprSet &Removables;
  201. public:
  202. RemovablesCollector(ExprSet &removables)
  203. : Removables(removables) { }
  204. bool shouldWalkTypesOfTypeLocs() const { return false; }
  205. bool TraverseStmtExpr(StmtExpr *E) {
  206. CompoundStmt *S = E->getSubStmt();
  207. for (CompoundStmt::body_iterator
  208. I = S->body_begin(), E = S->body_end(); I != E; ++I) {
  209. if (I != E - 1)
  210. mark(*I);
  211. TraverseStmt(*I);
  212. }
  213. return true;
  214. }
  215. bool VisitCompoundStmt(CompoundStmt *S) {
  216. for (auto *I : S->body())
  217. mark(I);
  218. return true;
  219. }
  220. bool VisitIfStmt(IfStmt *S) {
  221. mark(S->getThen());
  222. mark(S->getElse());
  223. return true;
  224. }
  225. bool VisitWhileStmt(WhileStmt *S) {
  226. mark(S->getBody());
  227. return true;
  228. }
  229. bool VisitDoStmt(DoStmt *S) {
  230. mark(S->getBody());
  231. return true;
  232. }
  233. bool VisitForStmt(ForStmt *S) {
  234. mark(S->getInit());
  235. mark(S->getInc());
  236. mark(S->getBody());
  237. return true;
  238. }
  239. private:
  240. void mark(Stmt *S) {
  241. if (!S) return;
  242. while (auto *Label = dyn_cast<LabelStmt>(S))
  243. S = Label->getSubStmt();
  244. if (auto *E = dyn_cast<Expr>(S))
  245. S = E->IgnoreImplicit();
  246. if (auto *E = dyn_cast<Expr>(S))
  247. Removables.insert(E);
  248. }
  249. };
  250. } // end anonymous namespace
  251. void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
  252. ReferenceClear(refs).TraverseStmt(S);
  253. }
  254. void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
  255. ReferenceCollector(D, refs).TraverseStmt(S);
  256. }
  257. void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
  258. RemovablesCollector(exprs).TraverseStmt(S);
  259. }
  260. //===----------------------------------------------------------------------===//
  261. // MigrationContext
  262. //===----------------------------------------------------------------------===//
  263. namespace {
  264. class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
  265. MigrationContext &MigrateCtx;
  266. typedef RecursiveASTVisitor<ASTTransform> base;
  267. public:
  268. ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
  269. bool shouldWalkTypesOfTypeLocs() const { return false; }
  270. bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
  271. ObjCImplementationContext ImplCtx(MigrateCtx, D);
  272. for (MigrationContext::traverser_iterator
  273. I = MigrateCtx.traversers_begin(),
  274. E = MigrateCtx.traversers_end(); I != E; ++I)
  275. (*I)->traverseObjCImplementation(ImplCtx);
  276. return base::TraverseObjCImplementationDecl(D);
  277. }
  278. bool TraverseStmt(Stmt *rootS) {
  279. if (!rootS)
  280. return true;
  281. BodyContext BodyCtx(MigrateCtx, rootS);
  282. for (MigrationContext::traverser_iterator
  283. I = MigrateCtx.traversers_begin(),
  284. E = MigrateCtx.traversers_end(); I != E; ++I)
  285. (*I)->traverseBody(BodyCtx);
  286. return true;
  287. }
  288. };
  289. }
  290. MigrationContext::~MigrationContext() {
  291. for (traverser_iterator
  292. I = traversers_begin(), E = traversers_end(); I != E; ++I)
  293. delete *I;
  294. }
  295. bool MigrationContext::isGCOwnedNonObjC(QualType T) {
  296. while (!T.isNull()) {
  297. if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
  298. if (AttrT->getAttrKind() == attr::ObjCOwnership)
  299. return !AttrT->getModifiedType()->isObjCRetainableType();
  300. }
  301. if (T->isArrayType())
  302. T = Pass.Ctx.getBaseElementType(T);
  303. else if (const PointerType *PT = T->getAs<PointerType>())
  304. T = PT->getPointeeType();
  305. else if (const ReferenceType *RT = T->getAs<ReferenceType>())
  306. T = RT->getPointeeType();
  307. else
  308. break;
  309. }
  310. return false;
  311. }
  312. bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
  313. StringRef toAttr,
  314. SourceLocation atLoc) {
  315. if (atLoc.isMacroID())
  316. return false;
  317. SourceManager &SM = Pass.Ctx.getSourceManager();
  318. // Break down the source location.
  319. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
  320. // Try to load the file buffer.
  321. bool invalidTemp = false;
  322. StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  323. if (invalidTemp)
  324. return false;
  325. const char *tokenBegin = file.data() + locInfo.second;
  326. // Lex from the start of the given location.
  327. Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
  328. Pass.Ctx.getLangOpts(),
  329. file.begin(), tokenBegin, file.end());
  330. Token tok;
  331. lexer.LexFromRawLexer(tok);
  332. if (tok.isNot(tok::at)) return false;
  333. lexer.LexFromRawLexer(tok);
  334. if (tok.isNot(tok::raw_identifier)) return false;
  335. if (tok.getRawIdentifier() != "property")
  336. return false;
  337. lexer.LexFromRawLexer(tok);
  338. if (tok.isNot(tok::l_paren)) return false;
  339. Token BeforeTok = tok;
  340. Token AfterTok;
  341. AfterTok.startToken();
  342. SourceLocation AttrLoc;
  343. lexer.LexFromRawLexer(tok);
  344. if (tok.is(tok::r_paren))
  345. return false;
  346. while (1) {
  347. if (tok.isNot(tok::raw_identifier)) return false;
  348. if (tok.getRawIdentifier() == fromAttr) {
  349. if (!toAttr.empty()) {
  350. Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
  351. return true;
  352. }
  353. // We want to remove the attribute.
  354. AttrLoc = tok.getLocation();
  355. }
  356. do {
  357. lexer.LexFromRawLexer(tok);
  358. if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
  359. AfterTok = tok;
  360. } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
  361. if (tok.is(tok::r_paren))
  362. break;
  363. if (AttrLoc.isInvalid())
  364. BeforeTok = tok;
  365. lexer.LexFromRawLexer(tok);
  366. }
  367. if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
  368. // We want to remove the attribute.
  369. if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
  370. Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
  371. AfterTok.getLocation()));
  372. } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
  373. Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
  374. } else {
  375. Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
  376. }
  377. return true;
  378. }
  379. return false;
  380. }
  381. bool MigrationContext::addPropertyAttribute(StringRef attr,
  382. SourceLocation atLoc) {
  383. if (atLoc.isMacroID())
  384. return false;
  385. SourceManager &SM = Pass.Ctx.getSourceManager();
  386. // Break down the source location.
  387. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
  388. // Try to load the file buffer.
  389. bool invalidTemp = false;
  390. StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  391. if (invalidTemp)
  392. return false;
  393. const char *tokenBegin = file.data() + locInfo.second;
  394. // Lex from the start of the given location.
  395. Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
  396. Pass.Ctx.getLangOpts(),
  397. file.begin(), tokenBegin, file.end());
  398. Token tok;
  399. lexer.LexFromRawLexer(tok);
  400. if (tok.isNot(tok::at)) return false;
  401. lexer.LexFromRawLexer(tok);
  402. if (tok.isNot(tok::raw_identifier)) return false;
  403. if (tok.getRawIdentifier() != "property")
  404. return false;
  405. lexer.LexFromRawLexer(tok);
  406. if (tok.isNot(tok::l_paren)) {
  407. Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
  408. return true;
  409. }
  410. lexer.LexFromRawLexer(tok);
  411. if (tok.is(tok::r_paren)) {
  412. Pass.TA.insert(tok.getLocation(), attr);
  413. return true;
  414. }
  415. if (tok.isNot(tok::raw_identifier)) return false;
  416. Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
  417. return true;
  418. }
  419. void MigrationContext::traverse(TranslationUnitDecl *TU) {
  420. for (traverser_iterator
  421. I = traversers_begin(), E = traversers_end(); I != E; ++I)
  422. (*I)->traverseTU(*this);
  423. ASTTransform(*this).TraverseDecl(TU);
  424. }
  425. static void GCRewriteFinalize(MigrationPass &pass) {
  426. ASTContext &Ctx = pass.Ctx;
  427. TransformActions &TA = pass.TA;
  428. DeclContext *DC = Ctx.getTranslationUnitDecl();
  429. Selector FinalizeSel =
  430. Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
  431. typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
  432. impl_iterator;
  433. for (impl_iterator I = impl_iterator(DC->decls_begin()),
  434. E = impl_iterator(DC->decls_end()); I != E; ++I) {
  435. for (const auto *MD : I->instance_methods()) {
  436. if (!MD->hasBody())
  437. continue;
  438. if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
  439. const ObjCMethodDecl *FinalizeM = MD;
  440. Transaction Trans(TA);
  441. TA.insert(FinalizeM->getSourceRange().getBegin(),
  442. "#if !__has_feature(objc_arc)\n");
  443. CharSourceRange::getTokenRange(FinalizeM->getSourceRange());
  444. const SourceManager &SM = pass.Ctx.getSourceManager();
  445. const LangOptions &LangOpts = pass.Ctx.getLangOpts();
  446. bool Invalid;
  447. std::string str = "\n#endif\n";
  448. str += Lexer::getSourceText(
  449. CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
  450. SM, LangOpts, &Invalid);
  451. TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str);
  452. break;
  453. }
  454. }
  455. }
  456. }
  457. //===----------------------------------------------------------------------===//
  458. // getAllTransformations.
  459. //===----------------------------------------------------------------------===//
  460. static void traverseAST(MigrationPass &pass) {
  461. MigrationContext MigrateCtx(pass);
  462. if (pass.isGCMigration()) {
  463. MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
  464. MigrateCtx.addTraverser(new GCAttrsTraverser());
  465. }
  466. MigrateCtx.addTraverser(new PropertyRewriteTraverser());
  467. MigrateCtx.addTraverser(new BlockObjCVariableTraverser());
  468. MigrateCtx.addTraverser(new ProtectedScopeTraverser());
  469. MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
  470. }
  471. static void independentTransforms(MigrationPass &pass) {
  472. rewriteAutoreleasePool(pass);
  473. removeRetainReleaseDeallocFinalize(pass);
  474. rewriteUnusedInitDelegate(pass);
  475. removeZeroOutPropsInDeallocFinalize(pass);
  476. makeAssignARCSafe(pass);
  477. rewriteUnbridgedCasts(pass);
  478. checkAPIUses(pass);
  479. traverseAST(pass);
  480. }
  481. std::vector<TransformFn> arcmt::getAllTransformations(
  482. LangOptions::GCMode OrigGCMode,
  483. bool NoFinalizeRemoval) {
  484. std::vector<TransformFn> transforms;
  485. if (OrigGCMode == LangOptions::GCOnly && NoFinalizeRemoval)
  486. transforms.push_back(GCRewriteFinalize);
  487. transforms.push_back(independentTransforms);
  488. // This depends on previous transformations removing various expressions.
  489. transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
  490. return transforms;
  491. }