Transforms.cpp 18 KB

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