ObjCMT.cpp 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290
  1. //===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
  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 "clang/ARCMigrate/ARCMT.h"
  11. #include "clang/ARCMigrate/ARCMTActions.h"
  12. #include "clang/AST/ASTConsumer.h"
  13. #include "clang/AST/ASTContext.h"
  14. #include "clang/AST/Attr.h"
  15. #include "clang/AST/NSAPI.h"
  16. #include "clang/AST/ParentMap.h"
  17. #include "clang/AST/RecursiveASTVisitor.h"
  18. #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
  19. #include "clang/Basic/FileManager.h"
  20. #include "clang/Edit/Commit.h"
  21. #include "clang/Edit/EditedSource.h"
  22. #include "clang/Edit/EditsReceiver.h"
  23. #include "clang/Edit/Rewriters.h"
  24. #include "clang/Frontend/CompilerInstance.h"
  25. #include "clang/Frontend/MultiplexConsumer.h"
  26. #include "clang/Lex/PPConditionalDirectiveRecord.h"
  27. #include "clang/Lex/Preprocessor.h"
  28. #include "clang/Rewrite/Core/Rewriter.h"
  29. #include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
  30. #include "llvm/ADT/SmallString.h"
  31. #include "llvm/ADT/StringSet.h"
  32. #include "llvm/Support/Path.h"
  33. #include "llvm/Support/SourceMgr.h"
  34. #include "llvm/Support/YAMLParser.h"
  35. using namespace clang;
  36. using namespace arcmt;
  37. using namespace ento::objc_retain;
  38. namespace {
  39. class ObjCMigrateASTConsumer : public ASTConsumer {
  40. enum CF_BRIDGING_KIND {
  41. CF_BRIDGING_NONE,
  42. CF_BRIDGING_ENABLE,
  43. CF_BRIDGING_MAY_INCLUDE
  44. };
  45. void migrateDecl(Decl *D);
  46. void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
  47. void migrateProtocolConformance(ASTContext &Ctx,
  48. const ObjCImplementationDecl *ImpDecl);
  49. void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
  50. bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
  51. const TypedefDecl *TypedefDcl);
  52. void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
  53. void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
  54. ObjCMethodDecl *OM);
  55. bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
  56. void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
  57. void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
  58. void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
  59. ObjCMethodDecl *OM,
  60. ObjCInstanceTypeFamily OIT_Family = OIT_None);
  61. void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
  62. void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
  63. const FunctionDecl *FuncDecl, bool ResultAnnotated);
  64. void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
  65. const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
  66. void AnnotateImplicitBridging(ASTContext &Ctx);
  67. CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
  68. const FunctionDecl *FuncDecl);
  69. void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
  70. void migrateAddMethodAnnotation(ASTContext &Ctx,
  71. const ObjCMethodDecl *MethodDecl);
  72. void inferDesignatedInitializers(ASTContext &Ctx,
  73. const ObjCImplementationDecl *ImplD);
  74. bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
  75. public:
  76. std::string MigrateDir;
  77. unsigned ASTMigrateActions;
  78. FileID FileId;
  79. const TypedefDecl *NSIntegerTypedefed;
  80. const TypedefDecl *NSUIntegerTypedefed;
  81. std::unique_ptr<NSAPI> NSAPIObj;
  82. std::unique_ptr<edit::EditedSource> Editor;
  83. FileRemapper &Remapper;
  84. FileManager &FileMgr;
  85. const PPConditionalDirectiveRecord *PPRec;
  86. Preprocessor &PP;
  87. bool IsOutputFile;
  88. bool FoundationIncluded;
  89. llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
  90. llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
  91. llvm::StringSet<> WhiteListFilenames;
  92. ObjCMigrateASTConsumer(StringRef migrateDir,
  93. unsigned astMigrateActions,
  94. FileRemapper &remapper,
  95. FileManager &fileMgr,
  96. const PPConditionalDirectiveRecord *PPRec,
  97. Preprocessor &PP,
  98. bool isOutputFile,
  99. ArrayRef<std::string> WhiteList)
  100. : MigrateDir(migrateDir),
  101. ASTMigrateActions(astMigrateActions),
  102. NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
  103. Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
  104. IsOutputFile(isOutputFile),
  105. FoundationIncluded(false){
  106. // FIXME: StringSet should have insert(iter, iter) to use here.
  107. for (const std::string &Val : WhiteList)
  108. WhiteListFilenames.insert(Val);
  109. }
  110. protected:
  111. void Initialize(ASTContext &Context) override {
  112. NSAPIObj.reset(new NSAPI(Context));
  113. Editor.reset(new edit::EditedSource(Context.getSourceManager(),
  114. Context.getLangOpts(),
  115. PPRec));
  116. }
  117. bool HandleTopLevelDecl(DeclGroupRef DG) override {
  118. for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
  119. migrateDecl(*I);
  120. return true;
  121. }
  122. void HandleInterestingDecl(DeclGroupRef DG) override {
  123. // Ignore decls from the PCH.
  124. }
  125. void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
  126. ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
  127. }
  128. void HandleTranslationUnit(ASTContext &Ctx) override;
  129. bool canModifyFile(StringRef Path) {
  130. if (WhiteListFilenames.empty())
  131. return true;
  132. return WhiteListFilenames.find(llvm::sys::path::filename(Path))
  133. != WhiteListFilenames.end();
  134. }
  135. bool canModifyFile(const FileEntry *FE) {
  136. if (!FE)
  137. return false;
  138. return canModifyFile(FE->getName());
  139. }
  140. bool canModifyFile(FileID FID) {
  141. if (FID.isInvalid())
  142. return false;
  143. return canModifyFile(PP.getSourceManager().getFileEntryForID(FID));
  144. }
  145. bool canModify(const Decl *D) {
  146. if (!D)
  147. return false;
  148. if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D))
  149. return canModify(CatImpl->getCategoryDecl());
  150. if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D))
  151. return canModify(Impl->getClassInterface());
  152. if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
  153. return canModify(cast<Decl>(MD->getDeclContext()));
  154. FileID FID = PP.getSourceManager().getFileID(D->getLocation());
  155. return canModifyFile(FID);
  156. }
  157. };
  158. }
  159. ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
  160. StringRef migrateDir,
  161. unsigned migrateAction)
  162. : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
  163. ObjCMigAction(migrateAction),
  164. CompInst(nullptr) {
  165. if (MigrateDir.empty())
  166. MigrateDir = "."; // user current directory if none is given.
  167. }
  168. std::unique_ptr<ASTConsumer>
  169. ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  170. PPConditionalDirectiveRecord *
  171. PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
  172. CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
  173. std::vector<std::unique_ptr<ASTConsumer>> Consumers;
  174. Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile));
  175. Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
  176. MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
  177. CompInst->getPreprocessor(), false, None));
  178. return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
  179. }
  180. bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
  181. Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
  182. /*ignoreIfFilesChanges=*/true);
  183. CompInst = &CI;
  184. CI.getDiagnostics().setIgnoreAllWarnings(true);
  185. return true;
  186. }
  187. namespace {
  188. // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
  189. bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
  190. const Expr* Expr = FullExpr->IgnoreImpCasts();
  191. if (isa<ArraySubscriptExpr>(Expr) ||
  192. isa<CallExpr>(Expr) ||
  193. isa<DeclRefExpr>(Expr) ||
  194. isa<CXXNamedCastExpr>(Expr) ||
  195. isa<CXXConstructExpr>(Expr) ||
  196. isa<CXXThisExpr>(Expr) ||
  197. isa<CXXTypeidExpr>(Expr) ||
  198. isa<CXXUnresolvedConstructExpr>(Expr) ||
  199. isa<ObjCMessageExpr>(Expr) ||
  200. isa<ObjCPropertyRefExpr>(Expr) ||
  201. isa<ObjCProtocolExpr>(Expr) ||
  202. isa<MemberExpr>(Expr) ||
  203. isa<ObjCIvarRefExpr>(Expr) ||
  204. isa<ParenExpr>(FullExpr) ||
  205. isa<ParenListExpr>(Expr) ||
  206. isa<SizeOfPackExpr>(Expr))
  207. return false;
  208. return true;
  209. }
  210. /// \brief - Rewrite message expression for Objective-C setter and getters into
  211. /// property-dot syntax.
  212. bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
  213. Preprocessor &PP,
  214. const NSAPI &NS, edit::Commit &commit,
  215. const ParentMap *PMap) {
  216. if (!Msg || Msg->isImplicit() ||
  217. (Msg->getReceiverKind() != ObjCMessageExpr::Instance &&
  218. Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance))
  219. return false;
  220. if (const Expr *Receiver = Msg->getInstanceReceiver())
  221. if (Receiver->getType()->isObjCBuiltinType())
  222. return false;
  223. const ObjCMethodDecl *Method = Msg->getMethodDecl();
  224. if (!Method)
  225. return false;
  226. if (!Method->isPropertyAccessor())
  227. return false;
  228. const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
  229. if (!Prop)
  230. return false;
  231. SourceRange MsgRange = Msg->getSourceRange();
  232. bool ReceiverIsSuper =
  233. (Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
  234. // for 'super' receiver is nullptr.
  235. const Expr *receiver = Msg->getInstanceReceiver();
  236. bool NeedsParen =
  237. ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver);
  238. bool IsGetter = (Msg->getNumArgs() == 0);
  239. if (IsGetter) {
  240. // Find space location range between receiver expression and getter method.
  241. SourceLocation BegLoc =
  242. ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd();
  243. BegLoc = PP.getLocForEndOfToken(BegLoc);
  244. SourceLocation EndLoc = Msg->getSelectorLoc(0);
  245. SourceRange SpaceRange(BegLoc, EndLoc);
  246. std::string PropertyDotString;
  247. // rewrite getter method expression into: receiver.property or
  248. // (receiver).property
  249. if (NeedsParen) {
  250. commit.insertBefore(receiver->getLocStart(), "(");
  251. PropertyDotString = ").";
  252. }
  253. else
  254. PropertyDotString = ".";
  255. PropertyDotString += Prop->getName();
  256. commit.replace(SpaceRange, PropertyDotString);
  257. // remove '[' ']'
  258. commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
  259. commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
  260. } else {
  261. if (NeedsParen)
  262. commit.insertWrap("(", receiver->getSourceRange(), ")");
  263. std::string PropertyDotString = ".";
  264. PropertyDotString += Prop->getName();
  265. PropertyDotString += " =";
  266. const Expr*const* Args = Msg->getArgs();
  267. const Expr *RHS = Args[0];
  268. if (!RHS)
  269. return false;
  270. SourceLocation BegLoc =
  271. ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd();
  272. BegLoc = PP.getLocForEndOfToken(BegLoc);
  273. SourceLocation EndLoc = RHS->getLocStart();
  274. EndLoc = EndLoc.getLocWithOffset(-1);
  275. const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
  276. // Add a space after '=' if there is no space between RHS and '='
  277. if (colon && colon[0] == ':')
  278. PropertyDotString += " ";
  279. SourceRange Range(BegLoc, EndLoc);
  280. commit.replace(Range, PropertyDotString);
  281. // remove '[' ']'
  282. commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
  283. commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
  284. }
  285. return true;
  286. }
  287. class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
  288. ObjCMigrateASTConsumer &Consumer;
  289. ParentMap &PMap;
  290. public:
  291. ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
  292. : Consumer(consumer), PMap(PMap) { }
  293. bool shouldVisitTemplateInstantiations() const { return false; }
  294. bool shouldWalkTypesOfTypeLocs() const { return false; }
  295. bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
  296. if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
  297. edit::Commit commit(*Consumer.Editor);
  298. edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
  299. Consumer.Editor->commit(commit);
  300. }
  301. if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
  302. edit::Commit commit(*Consumer.Editor);
  303. edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
  304. Consumer.Editor->commit(commit);
  305. }
  306. if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
  307. edit::Commit commit(*Consumer.Editor);
  308. rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
  309. commit, &PMap);
  310. Consumer.Editor->commit(commit);
  311. }
  312. return true;
  313. }
  314. bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
  315. // Do depth first; we want to rewrite the subexpressions first so that if
  316. // we have to move expressions we will move them already rewritten.
  317. for (Stmt *SubStmt : E->children())
  318. if (!TraverseStmt(SubStmt))
  319. return false;
  320. return WalkUpFromObjCMessageExpr(E);
  321. }
  322. };
  323. class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
  324. ObjCMigrateASTConsumer &Consumer;
  325. std::unique_ptr<ParentMap> PMap;
  326. public:
  327. BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
  328. bool shouldVisitTemplateInstantiations() const { return false; }
  329. bool shouldWalkTypesOfTypeLocs() const { return false; }
  330. bool TraverseStmt(Stmt *S) {
  331. PMap.reset(new ParentMap(S));
  332. ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
  333. return true;
  334. }
  335. };
  336. }
  337. void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
  338. if (!D)
  339. return;
  340. if (isa<ObjCMethodDecl>(D))
  341. return; // Wait for the ObjC container declaration.
  342. BodyMigrator(*this).TraverseDecl(D);
  343. }
  344. static void append_attr(std::string &PropertyString, const char *attr,
  345. bool &LParenAdded) {
  346. if (!LParenAdded) {
  347. PropertyString += "(";
  348. LParenAdded = true;
  349. }
  350. else
  351. PropertyString += ", ";
  352. PropertyString += attr;
  353. }
  354. static
  355. void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
  356. const std::string& TypeString,
  357. const char *name) {
  358. const char *argPtr = TypeString.c_str();
  359. int paren = 0;
  360. while (*argPtr) {
  361. switch (*argPtr) {
  362. case '(':
  363. PropertyString += *argPtr;
  364. paren++;
  365. break;
  366. case ')':
  367. PropertyString += *argPtr;
  368. paren--;
  369. break;
  370. case '^':
  371. case '*':
  372. PropertyString += (*argPtr);
  373. if (paren == 1) {
  374. PropertyString += name;
  375. name = "";
  376. }
  377. break;
  378. default:
  379. PropertyString += *argPtr;
  380. break;
  381. }
  382. argPtr++;
  383. }
  384. }
  385. static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
  386. Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
  387. bool RetainableObject = ArgType->isObjCRetainableType();
  388. if (RetainableObject &&
  389. (propertyLifetime == Qualifiers::OCL_Strong
  390. || propertyLifetime == Qualifiers::OCL_None)) {
  391. if (const ObjCObjectPointerType *ObjPtrTy =
  392. ArgType->getAs<ObjCObjectPointerType>()) {
  393. ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
  394. if (IDecl &&
  395. IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
  396. return "copy";
  397. else
  398. return "strong";
  399. }
  400. else if (ArgType->isBlockPointerType())
  401. return "copy";
  402. } else if (propertyLifetime == Qualifiers::OCL_Weak)
  403. // TODO. More precise determination of 'weak' attribute requires
  404. // looking into setter's implementation for backing weak ivar.
  405. return "weak";
  406. else if (RetainableObject)
  407. return ArgType->isBlockPointerType() ? "copy" : "strong";
  408. return nullptr;
  409. }
  410. static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
  411. const ObjCMethodDecl *Setter,
  412. const NSAPI &NS, edit::Commit &commit,
  413. unsigned LengthOfPrefix,
  414. bool Atomic, bool UseNsIosOnlyMacro,
  415. bool AvailabilityArgsMatch) {
  416. ASTContext &Context = NS.getASTContext();
  417. bool LParenAdded = false;
  418. std::string PropertyString = "@property ";
  419. if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {
  420. PropertyString += "(NS_NONATOMIC_IOSONLY";
  421. LParenAdded = true;
  422. } else if (!Atomic) {
  423. PropertyString += "(nonatomic";
  424. LParenAdded = true;
  425. }
  426. std::string PropertyNameString = Getter->getNameAsString();
  427. StringRef PropertyName(PropertyNameString);
  428. if (LengthOfPrefix > 0) {
  429. if (!LParenAdded) {
  430. PropertyString += "(getter=";
  431. LParenAdded = true;
  432. }
  433. else
  434. PropertyString += ", getter=";
  435. PropertyString += PropertyNameString;
  436. }
  437. // Property with no setter may be suggested as a 'readonly' property.
  438. if (!Setter)
  439. append_attr(PropertyString, "readonly", LParenAdded);
  440. // Short circuit 'delegate' properties that contain the name "delegate" or
  441. // "dataSource", or have exact name "target" to have 'assign' attribute.
  442. if (PropertyName.equals("target") ||
  443. (PropertyName.find("delegate") != StringRef::npos) ||
  444. (PropertyName.find("dataSource") != StringRef::npos)) {
  445. QualType QT = Getter->getReturnType();
  446. if (!QT->isRealType())
  447. append_attr(PropertyString, "assign", LParenAdded);
  448. } else if (!Setter) {
  449. QualType ResType = Context.getCanonicalType(Getter->getReturnType());
  450. if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
  451. append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
  452. } else {
  453. const ParmVarDecl *argDecl = *Setter->param_begin();
  454. QualType ArgType = Context.getCanonicalType(argDecl->getType());
  455. if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
  456. append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
  457. }
  458. if (LParenAdded)
  459. PropertyString += ')';
  460. QualType RT = Getter->getReturnType();
  461. if (!isa<TypedefType>(RT)) {
  462. // strip off any ARC lifetime qualifier.
  463. QualType CanResultTy = Context.getCanonicalType(RT);
  464. if (CanResultTy.getQualifiers().hasObjCLifetime()) {
  465. Qualifiers Qs = CanResultTy.getQualifiers();
  466. Qs.removeObjCLifetime();
  467. RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
  468. }
  469. }
  470. PropertyString += " ";
  471. PrintingPolicy SubPolicy(Context.getPrintingPolicy());
  472. SubPolicy.SuppressStrongLifetime = true;
  473. SubPolicy.SuppressLifetimeQualifiers = true;
  474. std::string TypeString = RT.getAsString(SubPolicy);
  475. if (LengthOfPrefix > 0) {
  476. // property name must strip off "is" and lower case the first character
  477. // after that; e.g. isContinuous will become continuous.
  478. StringRef PropertyNameStringRef(PropertyNameString);
  479. PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
  480. PropertyNameString = PropertyNameStringRef;
  481. bool NoLowering = (isUppercase(PropertyNameString[0]) &&
  482. PropertyNameString.size() > 1 &&
  483. isUppercase(PropertyNameString[1]));
  484. if (!NoLowering)
  485. PropertyNameString[0] = toLowercase(PropertyNameString[0]);
  486. }
  487. if (RT->isBlockPointerType() || RT->isFunctionPointerType())
  488. MigrateBlockOrFunctionPointerTypeVariable(PropertyString,
  489. TypeString,
  490. PropertyNameString.c_str());
  491. else {
  492. char LastChar = TypeString[TypeString.size()-1];
  493. PropertyString += TypeString;
  494. if (LastChar != '*')
  495. PropertyString += ' ';
  496. PropertyString += PropertyNameString;
  497. }
  498. SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
  499. Selector GetterSelector = Getter->getSelector();
  500. SourceLocation EndGetterSelectorLoc =
  501. StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
  502. commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
  503. EndGetterSelectorLoc),
  504. PropertyString);
  505. if (Setter && AvailabilityArgsMatch) {
  506. SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
  507. // Get location past ';'
  508. EndLoc = EndLoc.getLocWithOffset(1);
  509. SourceLocation BeginOfSetterDclLoc = Setter->getLocStart();
  510. // FIXME. This assumes that setter decl; is immediately preceded by eoln.
  511. // It is trying to remove the setter method decl. line entirely.
  512. BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
  513. commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
  514. }
  515. }
  516. static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) {
  517. if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) {
  518. StringRef Name = CatDecl->getName();
  519. return Name.endswith("Deprecated");
  520. }
  521. return false;
  522. }
  523. void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
  524. ObjCContainerDecl *D) {
  525. if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
  526. return;
  527. for (auto *Method : D->methods()) {
  528. if (Method->isDeprecated())
  529. continue;
  530. bool PropertyInferred = migrateProperty(Ctx, D, Method);
  531. // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
  532. // the getter method as it ends up on the property itself which we don't want
  533. // to do unless -objcmt-returns-innerpointer-property option is on.
  534. if (!PropertyInferred ||
  535. (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
  536. if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
  537. migrateNsReturnsInnerPointer(Ctx, Method);
  538. }
  539. if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
  540. return;
  541. for (auto *Prop : D->properties()) {
  542. if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
  543. !Prop->isDeprecated())
  544. migratePropertyNsReturnsInnerPointer(Ctx, Prop);
  545. }
  546. }
  547. static bool
  548. ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
  549. const ObjCImplementationDecl *ImpDecl,
  550. const ObjCInterfaceDecl *IDecl,
  551. ObjCProtocolDecl *Protocol) {
  552. // In auto-synthesis, protocol properties are not synthesized. So,
  553. // a conforming protocol must have its required properties declared
  554. // in class interface.
  555. bool HasAtleastOneRequiredProperty = false;
  556. if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
  557. for (const auto *Property : PDecl->properties()) {
  558. if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
  559. continue;
  560. HasAtleastOneRequiredProperty = true;
  561. DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
  562. if (R.size() == 0) {
  563. // Relax the rule and look into class's implementation for a synthesize
  564. // or dynamic declaration. Class is implementing a property coming from
  565. // another protocol. This still makes the target protocol as conforming.
  566. if (!ImpDecl->FindPropertyImplDecl(
  567. Property->getDeclName().getAsIdentifierInfo()))
  568. return false;
  569. }
  570. else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
  571. if ((ClassProperty->getPropertyAttributes()
  572. != Property->getPropertyAttributes()) ||
  573. !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
  574. return false;
  575. }
  576. else
  577. return false;
  578. }
  579. // At this point, all required properties in this protocol conform to those
  580. // declared in the class.
  581. // Check that class implements the required methods of the protocol too.
  582. bool HasAtleastOneRequiredMethod = false;
  583. if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
  584. if (PDecl->meth_begin() == PDecl->meth_end())
  585. return HasAtleastOneRequiredProperty;
  586. for (const auto *MD : PDecl->methods()) {
  587. if (MD->isImplicit())
  588. continue;
  589. if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
  590. continue;
  591. DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
  592. if (R.size() == 0)
  593. return false;
  594. bool match = false;
  595. HasAtleastOneRequiredMethod = true;
  596. for (unsigned I = 0, N = R.size(); I != N; ++I)
  597. if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
  598. if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
  599. match = true;
  600. break;
  601. }
  602. if (!match)
  603. return false;
  604. }
  605. }
  606. if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
  607. return true;
  608. return false;
  609. }
  610. static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
  611. llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
  612. const NSAPI &NS, edit::Commit &commit) {
  613. const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
  614. std::string ClassString;
  615. SourceLocation EndLoc =
  616. IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
  617. if (Protocols.empty()) {
  618. ClassString = '<';
  619. for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
  620. ClassString += ConformingProtocols[i]->getNameAsString();
  621. if (i != (e-1))
  622. ClassString += ", ";
  623. }
  624. ClassString += "> ";
  625. }
  626. else {
  627. ClassString = ", ";
  628. for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
  629. ClassString += ConformingProtocols[i]->getNameAsString();
  630. if (i != (e-1))
  631. ClassString += ", ";
  632. }
  633. ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
  634. EndLoc = *PL;
  635. }
  636. commit.insertAfterToken(EndLoc, ClassString);
  637. return true;
  638. }
  639. static StringRef GetUnsignedName(StringRef NSIntegerName) {
  640. StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
  641. .Case("int8_t", "uint8_t")
  642. .Case("int16_t", "uint16_t")
  643. .Case("int32_t", "uint32_t")
  644. .Case("NSInteger", "NSUInteger")
  645. .Case("int64_t", "uint64_t")
  646. .Default(NSIntegerName);
  647. return UnsignedName;
  648. }
  649. static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
  650. const TypedefDecl *TypedefDcl,
  651. const NSAPI &NS, edit::Commit &commit,
  652. StringRef NSIntegerName,
  653. bool NSOptions) {
  654. std::string ClassString;
  655. if (NSOptions) {
  656. ClassString = "typedef NS_OPTIONS(";
  657. ClassString += GetUnsignedName(NSIntegerName);
  658. }
  659. else {
  660. ClassString = "typedef NS_ENUM(";
  661. ClassString += NSIntegerName;
  662. }
  663. ClassString += ", ";
  664. ClassString += TypedefDcl->getIdentifier()->getName();
  665. ClassString += ')';
  666. SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
  667. commit.replace(R, ClassString);
  668. SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
  669. EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
  670. NS.getASTContext(), /*IsDecl*/true);
  671. if (!EndOfEnumDclLoc.isInvalid()) {
  672. SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
  673. commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
  674. }
  675. else
  676. return false;
  677. SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
  678. EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
  679. NS.getASTContext(), /*IsDecl*/true);
  680. if (!EndTypedefDclLoc.isInvalid()) {
  681. SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
  682. commit.remove(TDRange);
  683. }
  684. else
  685. return false;
  686. EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
  687. /*IsDecl*/true);
  688. if (!EndOfEnumDclLoc.isInvalid()) {
  689. SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
  690. // FIXME. This assumes that enum decl; is immediately preceded by eoln.
  691. // It is trying to remove the enum decl. lines entirely.
  692. BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
  693. commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
  694. return true;
  695. }
  696. return false;
  697. }
  698. static void rewriteToNSMacroDecl(ASTContext &Ctx,
  699. const EnumDecl *EnumDcl,
  700. const TypedefDecl *TypedefDcl,
  701. const NSAPI &NS, edit::Commit &commit,
  702. bool IsNSIntegerType) {
  703. QualType DesignatedEnumType = EnumDcl->getIntegerType();
  704. assert(!DesignatedEnumType.isNull()
  705. && "rewriteToNSMacroDecl - underlying enum type is null");
  706. PrintingPolicy Policy(Ctx.getPrintingPolicy());
  707. std::string TypeString = DesignatedEnumType.getAsString(Policy);
  708. std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
  709. ClassString += TypeString;
  710. ClassString += ", ";
  711. ClassString += TypedefDcl->getIdentifier()->getName();
  712. ClassString += ')';
  713. SourceLocation EndLoc;
  714. if (EnumDcl->getIntegerTypeSourceInfo()) {
  715. TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo();
  716. TypeLoc TLoc = TSourceInfo->getTypeLoc();
  717. EndLoc = TLoc.getLocEnd();
  718. const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc);
  719. unsigned count = 0;
  720. if (lbrace)
  721. while (lbrace[count] != '{')
  722. ++count;
  723. if (count > 0)
  724. EndLoc = EndLoc.getLocWithOffset(count-1);
  725. }
  726. else
  727. EndLoc = EnumDcl->getLocStart();
  728. SourceRange R(EnumDcl->getLocStart(), EndLoc);
  729. commit.replace(R, ClassString);
  730. // This is to remove spaces between '}' and typedef name.
  731. SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
  732. StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
  733. SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd();
  734. commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
  735. }
  736. static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
  737. const EnumDecl *EnumDcl) {
  738. bool PowerOfTwo = true;
  739. bool AllHexdecimalEnumerator = true;
  740. uint64_t MaxPowerOfTwoVal = 0;
  741. for (auto Enumerator : EnumDcl->enumerators()) {
  742. const Expr *InitExpr = Enumerator->getInitExpr();
  743. if (!InitExpr) {
  744. PowerOfTwo = false;
  745. AllHexdecimalEnumerator = false;
  746. continue;
  747. }
  748. InitExpr = InitExpr->IgnoreParenCasts();
  749. if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
  750. if (BO->isShiftOp() || BO->isBitwiseOp())
  751. return true;
  752. uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
  753. if (PowerOfTwo && EnumVal) {
  754. if (!llvm::isPowerOf2_64(EnumVal))
  755. PowerOfTwo = false;
  756. else if (EnumVal > MaxPowerOfTwoVal)
  757. MaxPowerOfTwoVal = EnumVal;
  758. }
  759. if (AllHexdecimalEnumerator && EnumVal) {
  760. bool FoundHexdecimalEnumerator = false;
  761. SourceLocation EndLoc = Enumerator->getLocEnd();
  762. Token Tok;
  763. if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
  764. if (Tok.isLiteral() && Tok.getLength() > 2) {
  765. if (const char *StringLit = Tok.getLiteralData())
  766. FoundHexdecimalEnumerator =
  767. (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
  768. }
  769. if (!FoundHexdecimalEnumerator)
  770. AllHexdecimalEnumerator = false;
  771. }
  772. }
  773. return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
  774. }
  775. void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
  776. const ObjCImplementationDecl *ImpDecl) {
  777. const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
  778. if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
  779. return;
  780. // Find all implicit conforming protocols for this class
  781. // and make them explicit.
  782. llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
  783. Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
  784. llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
  785. for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
  786. if (!ExplicitProtocols.count(ProtDecl))
  787. PotentialImplicitProtocols.push_back(ProtDecl);
  788. if (PotentialImplicitProtocols.empty())
  789. return;
  790. // go through list of non-optional methods and properties in each protocol
  791. // in the PotentialImplicitProtocols list. If class implements every one of the
  792. // methods and properties, then this class conforms to this protocol.
  793. llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
  794. for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
  795. if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
  796. PotentialImplicitProtocols[i]))
  797. ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
  798. if (ConformingProtocols.empty())
  799. return;
  800. // Further reduce number of conforming protocols. If protocol P1 is in the list
  801. // protocol P2 (P2<P1>), No need to include P1.
  802. llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
  803. for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
  804. bool DropIt = false;
  805. ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
  806. for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
  807. ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
  808. if (PDecl == TargetPDecl)
  809. continue;
  810. if (PDecl->lookupProtocolNamed(
  811. TargetPDecl->getDeclName().getAsIdentifierInfo())) {
  812. DropIt = true;
  813. break;
  814. }
  815. }
  816. if (!DropIt)
  817. MinimalConformingProtocols.push_back(TargetPDecl);
  818. }
  819. if (MinimalConformingProtocols.empty())
  820. return;
  821. edit::Commit commit(*Editor);
  822. rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
  823. *NSAPIObj, commit);
  824. Editor->commit(commit);
  825. }
  826. void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
  827. const TypedefDecl *TypedefDcl) {
  828. QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
  829. if (NSAPIObj->isObjCNSIntegerType(qt))
  830. NSIntegerTypedefed = TypedefDcl;
  831. else if (NSAPIObj->isObjCNSUIntegerType(qt))
  832. NSUIntegerTypedefed = TypedefDcl;
  833. }
  834. bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
  835. const EnumDecl *EnumDcl,
  836. const TypedefDecl *TypedefDcl) {
  837. if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
  838. EnumDcl->isDeprecated())
  839. return false;
  840. if (!TypedefDcl) {
  841. if (NSIntegerTypedefed) {
  842. TypedefDcl = NSIntegerTypedefed;
  843. NSIntegerTypedefed = nullptr;
  844. }
  845. else if (NSUIntegerTypedefed) {
  846. TypedefDcl = NSUIntegerTypedefed;
  847. NSUIntegerTypedefed = nullptr;
  848. }
  849. else
  850. return false;
  851. FileID FileIdOfTypedefDcl =
  852. PP.getSourceManager().getFileID(TypedefDcl->getLocation());
  853. FileID FileIdOfEnumDcl =
  854. PP.getSourceManager().getFileID(EnumDcl->getLocation());
  855. if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
  856. return false;
  857. }
  858. if (TypedefDcl->isDeprecated())
  859. return false;
  860. QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
  861. StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
  862. if (NSIntegerName.empty()) {
  863. // Also check for typedef enum {...} TD;
  864. if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
  865. if (EnumTy->getDecl() == EnumDcl) {
  866. bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
  867. if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
  868. return false;
  869. edit::Commit commit(*Editor);
  870. rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
  871. Editor->commit(commit);
  872. return true;
  873. }
  874. }
  875. return false;
  876. }
  877. // We may still use NS_OPTIONS based on what we find in the enumertor list.
  878. bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
  879. if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
  880. return false;
  881. edit::Commit commit(*Editor);
  882. bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
  883. commit, NSIntegerName, NSOptions);
  884. Editor->commit(commit);
  885. return Res;
  886. }
  887. static void ReplaceWithInstancetype(ASTContext &Ctx,
  888. const ObjCMigrateASTConsumer &ASTC,
  889. ObjCMethodDecl *OM) {
  890. if (OM->getReturnType() == Ctx.getObjCInstanceType())
  891. return; // already has instancetype.
  892. SourceRange R;
  893. std::string ClassString;
  894. if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
  895. TypeLoc TL = TSInfo->getTypeLoc();
  896. R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
  897. ClassString = "instancetype";
  898. }
  899. else {
  900. R = SourceRange(OM->getLocStart(), OM->getLocStart());
  901. ClassString = OM->isInstanceMethod() ? '-' : '+';
  902. ClassString += " (instancetype)";
  903. }
  904. edit::Commit commit(*ASTC.Editor);
  905. commit.replace(R, ClassString);
  906. ASTC.Editor->commit(commit);
  907. }
  908. static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
  909. ObjCMethodDecl *OM) {
  910. ObjCInterfaceDecl *IDecl = OM->getClassInterface();
  911. SourceRange R;
  912. std::string ClassString;
  913. if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
  914. TypeLoc TL = TSInfo->getTypeLoc();
  915. R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
  916. ClassString = IDecl->getName();
  917. ClassString += "*";
  918. }
  919. }
  920. else {
  921. R = SourceRange(OM->getLocStart(), OM->getLocStart());
  922. ClassString = "+ (";
  923. ClassString += IDecl->getName(); ClassString += "*)";
  924. }
  925. edit::Commit commit(*ASTC.Editor);
  926. commit.replace(R, ClassString);
  927. ASTC.Editor->commit(commit);
  928. }
  929. void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
  930. ObjCContainerDecl *CDecl,
  931. ObjCMethodDecl *OM) {
  932. ObjCInstanceTypeFamily OIT_Family =
  933. Selector::getInstTypeMethodFamily(OM->getSelector());
  934. std::string ClassName;
  935. switch (OIT_Family) {
  936. case OIT_None:
  937. migrateFactoryMethod(Ctx, CDecl, OM);
  938. return;
  939. case OIT_Array:
  940. ClassName = "NSArray";
  941. break;
  942. case OIT_Dictionary:
  943. ClassName = "NSDictionary";
  944. break;
  945. case OIT_Singleton:
  946. migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
  947. return;
  948. case OIT_Init:
  949. if (OM->getReturnType()->isObjCIdType())
  950. ReplaceWithInstancetype(Ctx, *this, OM);
  951. return;
  952. case OIT_ReturnsSelf:
  953. migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
  954. return;
  955. }
  956. if (!OM->getReturnType()->isObjCIdType())
  957. return;
  958. ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
  959. if (!IDecl) {
  960. if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
  961. IDecl = CatDecl->getClassInterface();
  962. else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
  963. IDecl = ImpDecl->getClassInterface();
  964. }
  965. if (!IDecl ||
  966. !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
  967. migrateFactoryMethod(Ctx, CDecl, OM);
  968. return;
  969. }
  970. ReplaceWithInstancetype(Ctx, *this, OM);
  971. }
  972. static bool TypeIsInnerPointer(QualType T) {
  973. if (!T->isAnyPointerType())
  974. return false;
  975. if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
  976. T->isBlockPointerType() || T->isFunctionPointerType() ||
  977. ento::coreFoundation::isCFObjectRef(T))
  978. return false;
  979. // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
  980. // is not an innter pointer type.
  981. QualType OrigT = T;
  982. while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr()))
  983. T = TD->getDecl()->getUnderlyingType();
  984. if (OrigT == T || !T->isPointerType())
  985. return true;
  986. const PointerType* PT = T->getAs<PointerType>();
  987. QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
  988. if (UPointeeT->isRecordType()) {
  989. const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
  990. if (!RecordTy->getDecl()->isCompleteDefinition())
  991. return false;
  992. }
  993. return true;
  994. }
  995. /// \brief Check whether the two versions match.
  996. static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
  997. return (X == Y);
  998. }
  999. /// AvailabilityAttrsMatch - This routine checks that if comparing two
  1000. /// availability attributes, all their components match. It returns
  1001. /// true, if not dealing with availability or when all components of
  1002. /// availability attributes match. This routine is only called when
  1003. /// the attributes are of the same kind.
  1004. static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
  1005. const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
  1006. if (!AA1)
  1007. return true;
  1008. const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
  1009. VersionTuple Introduced1 = AA1->getIntroduced();
  1010. VersionTuple Deprecated1 = AA1->getDeprecated();
  1011. VersionTuple Obsoleted1 = AA1->getObsoleted();
  1012. bool IsUnavailable1 = AA1->getUnavailable();
  1013. VersionTuple Introduced2 = AA2->getIntroduced();
  1014. VersionTuple Deprecated2 = AA2->getDeprecated();
  1015. VersionTuple Obsoleted2 = AA2->getObsoleted();
  1016. bool IsUnavailable2 = AA2->getUnavailable();
  1017. return (versionsMatch(Introduced1, Introduced2) &&
  1018. versionsMatch(Deprecated1, Deprecated2) &&
  1019. versionsMatch(Obsoleted1, Obsoleted2) &&
  1020. IsUnavailable1 == IsUnavailable2);
  1021. }
  1022. static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
  1023. bool &AvailabilityArgsMatch) {
  1024. // This list is very small, so this need not be optimized.
  1025. for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
  1026. bool match = false;
  1027. for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
  1028. // Matching attribute kind only. Except for Availabilty attributes,
  1029. // we are not getting into details of the attributes. For all practical purposes
  1030. // this is sufficient.
  1031. if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
  1032. if (AvailabilityArgsMatch)
  1033. AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
  1034. match = true;
  1035. break;
  1036. }
  1037. }
  1038. if (!match)
  1039. return false;
  1040. }
  1041. return true;
  1042. }
  1043. /// AttributesMatch - This routine checks list of attributes for two
  1044. /// decls. It returns false, if there is a mismatch in kind of
  1045. /// attributes seen in the decls. It returns true if the two decls
  1046. /// have list of same kind of attributes. Furthermore, when there
  1047. /// are availability attributes in the two decls, it sets the
  1048. /// AvailabilityArgsMatch to false if availability attributes have
  1049. /// different versions, etc.
  1050. static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
  1051. bool &AvailabilityArgsMatch) {
  1052. if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
  1053. AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
  1054. return true;
  1055. }
  1056. AvailabilityArgsMatch = true;
  1057. const AttrVec &Attrs1 = Decl1->getAttrs();
  1058. const AttrVec &Attrs2 = Decl2->getAttrs();
  1059. bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
  1060. if (match && (Attrs2.size() > Attrs1.size()))
  1061. return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
  1062. return match;
  1063. }
  1064. static bool IsValidIdentifier(ASTContext &Ctx,
  1065. const char *Name) {
  1066. if (!isIdentifierHead(Name[0]))
  1067. return false;
  1068. std::string NameString = Name;
  1069. NameString[0] = toLowercase(NameString[0]);
  1070. IdentifierInfo *II = &Ctx.Idents.get(NameString);
  1071. return II->getTokenID() == tok::identifier;
  1072. }
  1073. bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
  1074. ObjCContainerDecl *D,
  1075. ObjCMethodDecl *Method) {
  1076. if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
  1077. Method->param_size() != 0)
  1078. return false;
  1079. // Is this method candidate to be a getter?
  1080. QualType GRT = Method->getReturnType();
  1081. if (GRT->isVoidType())
  1082. return false;
  1083. Selector GetterSelector = Method->getSelector();
  1084. ObjCInstanceTypeFamily OIT_Family =
  1085. Selector::getInstTypeMethodFamily(GetterSelector);
  1086. if (OIT_Family != OIT_None)
  1087. return false;
  1088. IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
  1089. Selector SetterSelector =
  1090. SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
  1091. PP.getSelectorTable(),
  1092. getterName);
  1093. ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
  1094. unsigned LengthOfPrefix = 0;
  1095. if (!SetterMethod) {
  1096. // try a different naming convention for getter: isXxxxx
  1097. StringRef getterNameString = getterName->getName();
  1098. bool IsPrefix = getterNameString.startswith("is");
  1099. // Note that we don't want to change an isXXX method of retainable object
  1100. // type to property (readonly or otherwise).
  1101. if (IsPrefix && GRT->isObjCRetainableType())
  1102. return false;
  1103. if (IsPrefix || getterNameString.startswith("get")) {
  1104. LengthOfPrefix = (IsPrefix ? 2 : 3);
  1105. const char *CGetterName = getterNameString.data() + LengthOfPrefix;
  1106. // Make sure that first character after "is" or "get" prefix can
  1107. // start an identifier.
  1108. if (!IsValidIdentifier(Ctx, CGetterName))
  1109. return false;
  1110. if (CGetterName[0] && isUppercase(CGetterName[0])) {
  1111. getterName = &Ctx.Idents.get(CGetterName);
  1112. SetterSelector =
  1113. SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
  1114. PP.getSelectorTable(),
  1115. getterName);
  1116. SetterMethod = D->getInstanceMethod(SetterSelector);
  1117. }
  1118. }
  1119. }
  1120. if (SetterMethod) {
  1121. if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
  1122. return false;
  1123. bool AvailabilityArgsMatch;
  1124. if (SetterMethod->isDeprecated() ||
  1125. !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
  1126. return false;
  1127. // Is this a valid setter, matching the target getter?
  1128. QualType SRT = SetterMethod->getReturnType();
  1129. if (!SRT->isVoidType())
  1130. return false;
  1131. const ParmVarDecl *argDecl = *SetterMethod->param_begin();
  1132. QualType ArgType = argDecl->getType();
  1133. if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
  1134. return false;
  1135. edit::Commit commit(*Editor);
  1136. rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
  1137. LengthOfPrefix,
  1138. (ASTMigrateActions &
  1139. FrontendOptions::ObjCMT_AtomicProperty) != 0,
  1140. (ASTMigrateActions &
  1141. FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
  1142. AvailabilityArgsMatch);
  1143. Editor->commit(commit);
  1144. return true;
  1145. }
  1146. else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
  1147. // Try a non-void method with no argument (and no setter or property of same name
  1148. // as a 'readonly' property.
  1149. edit::Commit commit(*Editor);
  1150. rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
  1151. LengthOfPrefix,
  1152. (ASTMigrateActions &
  1153. FrontendOptions::ObjCMT_AtomicProperty) != 0,
  1154. (ASTMigrateActions &
  1155. FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
  1156. /*AvailabilityArgsMatch*/false);
  1157. Editor->commit(commit);
  1158. return true;
  1159. }
  1160. return false;
  1161. }
  1162. void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
  1163. ObjCMethodDecl *OM) {
  1164. if (OM->isImplicit() ||
  1165. !OM->isInstanceMethod() ||
  1166. OM->hasAttr<ObjCReturnsInnerPointerAttr>())
  1167. return;
  1168. QualType RT = OM->getReturnType();
  1169. if (!TypeIsInnerPointer(RT) ||
  1170. !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
  1171. return;
  1172. edit::Commit commit(*Editor);
  1173. commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
  1174. Editor->commit(commit);
  1175. }
  1176. void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
  1177. ObjCPropertyDecl *P) {
  1178. QualType T = P->getType();
  1179. if (!TypeIsInnerPointer(T) ||
  1180. !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
  1181. return;
  1182. edit::Commit commit(*Editor);
  1183. commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER ");
  1184. Editor->commit(commit);
  1185. }
  1186. void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
  1187. ObjCContainerDecl *CDecl) {
  1188. if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
  1189. return;
  1190. // migrate methods which can have instancetype as their result type.
  1191. for (auto *Method : CDecl->methods()) {
  1192. if (Method->isDeprecated())
  1193. continue;
  1194. migrateMethodInstanceType(Ctx, CDecl, Method);
  1195. }
  1196. }
  1197. void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
  1198. ObjCContainerDecl *CDecl,
  1199. ObjCMethodDecl *OM,
  1200. ObjCInstanceTypeFamily OIT_Family) {
  1201. if (OM->isInstanceMethod() ||
  1202. OM->getReturnType() == Ctx.getObjCInstanceType() ||
  1203. !OM->getReturnType()->isObjCIdType())
  1204. return;
  1205. // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
  1206. // NSYYYNamE with matching names be at least 3 characters long.
  1207. ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
  1208. if (!IDecl) {
  1209. if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
  1210. IDecl = CatDecl->getClassInterface();
  1211. else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
  1212. IDecl = ImpDecl->getClassInterface();
  1213. }
  1214. if (!IDecl)
  1215. return;
  1216. std::string StringClassName = IDecl->getName();
  1217. StringRef LoweredClassName(StringClassName);
  1218. std::string StringLoweredClassName = LoweredClassName.lower();
  1219. LoweredClassName = StringLoweredClassName;
  1220. IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
  1221. // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
  1222. if (!MethodIdName)
  1223. return;
  1224. std::string MethodName = MethodIdName->getName();
  1225. if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
  1226. StringRef STRefMethodName(MethodName);
  1227. size_t len = 0;
  1228. if (STRefMethodName.startswith("standard"))
  1229. len = strlen("standard");
  1230. else if (STRefMethodName.startswith("shared"))
  1231. len = strlen("shared");
  1232. else if (STRefMethodName.startswith("default"))
  1233. len = strlen("default");
  1234. else
  1235. return;
  1236. MethodName = STRefMethodName.substr(len);
  1237. }
  1238. std::string MethodNameSubStr = MethodName.substr(0, 3);
  1239. StringRef MethodNamePrefix(MethodNameSubStr);
  1240. std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
  1241. MethodNamePrefix = StringLoweredMethodNamePrefix;
  1242. size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
  1243. if (Ix == StringRef::npos)
  1244. return;
  1245. std::string ClassNamePostfix = LoweredClassName.substr(Ix);
  1246. StringRef LoweredMethodName(MethodName);
  1247. std::string StringLoweredMethodName = LoweredMethodName.lower();
  1248. LoweredMethodName = StringLoweredMethodName;
  1249. if (!LoweredMethodName.startswith(ClassNamePostfix))
  1250. return;
  1251. if (OIT_Family == OIT_ReturnsSelf)
  1252. ReplaceWithClasstype(*this, OM);
  1253. else
  1254. ReplaceWithInstancetype(Ctx, *this, OM);
  1255. }
  1256. static bool IsVoidStarType(QualType Ty) {
  1257. if (!Ty->isPointerType())
  1258. return false;
  1259. while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
  1260. Ty = TD->getDecl()->getUnderlyingType();
  1261. // Is the type void*?
  1262. const PointerType* PT = Ty->getAs<PointerType>();
  1263. if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
  1264. return true;
  1265. return IsVoidStarType(PT->getPointeeType());
  1266. }
  1267. /// AuditedType - This routine audits the type AT and returns false if it is one of known
  1268. /// CF object types or of the "void *" variety. It returns true if we don't care about the type
  1269. /// such as a non-pointer or pointers which have no ownership issues (such as "int *").
  1270. static bool AuditedType (QualType AT) {
  1271. if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
  1272. return true;
  1273. // FIXME. There isn't much we can say about CF pointer type; or is there?
  1274. if (ento::coreFoundation::isCFObjectRef(AT) ||
  1275. IsVoidStarType(AT) ||
  1276. // If an ObjC object is type, assuming that it is not a CF function and
  1277. // that it is an un-audited function.
  1278. AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
  1279. return false;
  1280. // All other pointers are assumed audited as harmless.
  1281. return true;
  1282. }
  1283. void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
  1284. if (CFFunctionIBCandidates.empty())
  1285. return;
  1286. if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {
  1287. CFFunctionIBCandidates.clear();
  1288. FileId = FileID();
  1289. return;
  1290. }
  1291. // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
  1292. const Decl *FirstFD = CFFunctionIBCandidates[0];
  1293. const Decl *LastFD =
  1294. CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
  1295. const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
  1296. edit::Commit commit(*Editor);
  1297. commit.insertBefore(FirstFD->getLocStart(), PragmaString);
  1298. PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
  1299. SourceLocation EndLoc = LastFD->getLocEnd();
  1300. // get location just past end of function location.
  1301. EndLoc = PP.getLocForEndOfToken(EndLoc);
  1302. if (isa<FunctionDecl>(LastFD)) {
  1303. // For Methods, EndLoc points to the ending semcolon. So,
  1304. // not of these extra work is needed.
  1305. Token Tok;
  1306. // get locaiton of token that comes after end of function.
  1307. bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
  1308. if (!Failed)
  1309. EndLoc = Tok.getLocation();
  1310. }
  1311. commit.insertAfterToken(EndLoc, PragmaString);
  1312. Editor->commit(commit);
  1313. FileId = FileID();
  1314. CFFunctionIBCandidates.clear();
  1315. }
  1316. void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
  1317. if (Decl->isDeprecated())
  1318. return;
  1319. if (Decl->hasAttr<CFAuditedTransferAttr>()) {
  1320. assert(CFFunctionIBCandidates.empty() &&
  1321. "Cannot have audited functions/methods inside user "
  1322. "provided CF_IMPLICIT_BRIDGING_ENABLE");
  1323. return;
  1324. }
  1325. // Finction must be annotated first.
  1326. if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
  1327. CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
  1328. if (AuditKind == CF_BRIDGING_ENABLE) {
  1329. CFFunctionIBCandidates.push_back(Decl);
  1330. if (FileId.isInvalid())
  1331. FileId = PP.getSourceManager().getFileID(Decl->getLocation());
  1332. }
  1333. else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
  1334. if (!CFFunctionIBCandidates.empty()) {
  1335. CFFunctionIBCandidates.push_back(Decl);
  1336. if (FileId.isInvalid())
  1337. FileId = PP.getSourceManager().getFileID(Decl->getLocation());
  1338. }
  1339. }
  1340. else
  1341. AnnotateImplicitBridging(Ctx);
  1342. }
  1343. else {
  1344. migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
  1345. AnnotateImplicitBridging(Ctx);
  1346. }
  1347. }
  1348. void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
  1349. const CallEffects &CE,
  1350. const FunctionDecl *FuncDecl,
  1351. bool ResultAnnotated) {
  1352. // Annotate function.
  1353. if (!ResultAnnotated) {
  1354. RetEffect Ret = CE.getReturnValue();
  1355. const char *AnnotationString = nullptr;
  1356. if (Ret.getObjKind() == RetEffect::CF) {
  1357. if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
  1358. AnnotationString = " CF_RETURNS_RETAINED";
  1359. else if (Ret.notOwned() &&
  1360. NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
  1361. AnnotationString = " CF_RETURNS_NOT_RETAINED";
  1362. }
  1363. else if (Ret.getObjKind() == RetEffect::ObjC) {
  1364. if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
  1365. AnnotationString = " NS_RETURNS_RETAINED";
  1366. }
  1367. if (AnnotationString) {
  1368. edit::Commit commit(*Editor);
  1369. commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
  1370. Editor->commit(commit);
  1371. }
  1372. }
  1373. ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  1374. unsigned i = 0;
  1375. for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
  1376. pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
  1377. const ParmVarDecl *pd = *pi;
  1378. ArgEffect AE = AEArgs[i];
  1379. if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
  1380. NSAPIObj->isMacroDefined("CF_CONSUMED")) {
  1381. edit::Commit commit(*Editor);
  1382. commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
  1383. Editor->commit(commit);
  1384. }
  1385. else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
  1386. NSAPIObj->isMacroDefined("NS_CONSUMED")) {
  1387. edit::Commit commit(*Editor);
  1388. commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
  1389. Editor->commit(commit);
  1390. }
  1391. }
  1392. }
  1393. ObjCMigrateASTConsumer::CF_BRIDGING_KIND
  1394. ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
  1395. ASTContext &Ctx,
  1396. const FunctionDecl *FuncDecl) {
  1397. if (FuncDecl->hasBody())
  1398. return CF_BRIDGING_NONE;
  1399. CallEffects CE = CallEffects::getEffect(FuncDecl);
  1400. bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
  1401. FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
  1402. FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
  1403. FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
  1404. FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
  1405. // Trivial case of when funciton is annotated and has no argument.
  1406. if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
  1407. return CF_BRIDGING_NONE;
  1408. bool ReturnCFAudited = false;
  1409. if (!FuncIsReturnAnnotated) {
  1410. RetEffect Ret = CE.getReturnValue();
  1411. if (Ret.getObjKind() == RetEffect::CF &&
  1412. (Ret.isOwned() || Ret.notOwned()))
  1413. ReturnCFAudited = true;
  1414. else if (!AuditedType(FuncDecl->getReturnType()))
  1415. return CF_BRIDGING_NONE;
  1416. }
  1417. // At this point result type is audited for potential inclusion.
  1418. // Now, how about argument types.
  1419. ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  1420. unsigned i = 0;
  1421. bool ArgCFAudited = false;
  1422. for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
  1423. pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
  1424. const ParmVarDecl *pd = *pi;
  1425. ArgEffect AE = AEArgs[i];
  1426. if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
  1427. if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
  1428. ArgCFAudited = true;
  1429. else if (AE == IncRef)
  1430. ArgCFAudited = true;
  1431. }
  1432. else {
  1433. QualType AT = pd->getType();
  1434. if (!AuditedType(AT)) {
  1435. AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
  1436. return CF_BRIDGING_NONE;
  1437. }
  1438. }
  1439. }
  1440. if (ReturnCFAudited || ArgCFAudited)
  1441. return CF_BRIDGING_ENABLE;
  1442. return CF_BRIDGING_MAY_INCLUDE;
  1443. }
  1444. void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
  1445. ObjCContainerDecl *CDecl) {
  1446. if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
  1447. return;
  1448. // migrate methods which can have instancetype as their result type.
  1449. for (const auto *Method : CDecl->methods())
  1450. migrateCFAnnotation(Ctx, Method);
  1451. }
  1452. void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
  1453. const CallEffects &CE,
  1454. const ObjCMethodDecl *MethodDecl,
  1455. bool ResultAnnotated) {
  1456. // Annotate function.
  1457. if (!ResultAnnotated) {
  1458. RetEffect Ret = CE.getReturnValue();
  1459. const char *AnnotationString = nullptr;
  1460. if (Ret.getObjKind() == RetEffect::CF) {
  1461. if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
  1462. AnnotationString = " CF_RETURNS_RETAINED";
  1463. else if (Ret.notOwned() &&
  1464. NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
  1465. AnnotationString = " CF_RETURNS_NOT_RETAINED";
  1466. }
  1467. else if (Ret.getObjKind() == RetEffect::ObjC) {
  1468. ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
  1469. switch (OMF) {
  1470. case clang::OMF_alloc:
  1471. case clang::OMF_new:
  1472. case clang::OMF_copy:
  1473. case clang::OMF_init:
  1474. case clang::OMF_mutableCopy:
  1475. break;
  1476. default:
  1477. if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
  1478. AnnotationString = " NS_RETURNS_RETAINED";
  1479. break;
  1480. }
  1481. }
  1482. if (AnnotationString) {
  1483. edit::Commit commit(*Editor);
  1484. commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
  1485. Editor->commit(commit);
  1486. }
  1487. }
  1488. ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  1489. unsigned i = 0;
  1490. for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
  1491. pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
  1492. const ParmVarDecl *pd = *pi;
  1493. ArgEffect AE = AEArgs[i];
  1494. if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
  1495. NSAPIObj->isMacroDefined("CF_CONSUMED")) {
  1496. edit::Commit commit(*Editor);
  1497. commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
  1498. Editor->commit(commit);
  1499. }
  1500. }
  1501. }
  1502. void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
  1503. ASTContext &Ctx,
  1504. const ObjCMethodDecl *MethodDecl) {
  1505. if (MethodDecl->hasBody() || MethodDecl->isImplicit())
  1506. return;
  1507. CallEffects CE = CallEffects::getEffect(MethodDecl);
  1508. bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
  1509. MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
  1510. MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
  1511. MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
  1512. MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
  1513. if (CE.getReceiver() == DecRefMsg &&
  1514. !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
  1515. MethodDecl->getMethodFamily() != OMF_init &&
  1516. MethodDecl->getMethodFamily() != OMF_release &&
  1517. NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
  1518. edit::Commit commit(*Editor);
  1519. commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
  1520. Editor->commit(commit);
  1521. }
  1522. // Trivial case of when funciton is annotated and has no argument.
  1523. if (MethodIsReturnAnnotated &&
  1524. (MethodDecl->param_begin() == MethodDecl->param_end()))
  1525. return;
  1526. if (!MethodIsReturnAnnotated) {
  1527. RetEffect Ret = CE.getReturnValue();
  1528. if ((Ret.getObjKind() == RetEffect::CF ||
  1529. Ret.getObjKind() == RetEffect::ObjC) &&
  1530. (Ret.isOwned() || Ret.notOwned())) {
  1531. AddCFAnnotations(Ctx, CE, MethodDecl, false);
  1532. return;
  1533. } else if (!AuditedType(MethodDecl->getReturnType()))
  1534. return;
  1535. }
  1536. // At this point result type is either annotated or audited.
  1537. // Now, how about argument types.
  1538. ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  1539. unsigned i = 0;
  1540. for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
  1541. pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
  1542. const ParmVarDecl *pd = *pi;
  1543. ArgEffect AE = AEArgs[i];
  1544. if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
  1545. !AuditedType(pd->getType())) {
  1546. AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
  1547. return;
  1548. }
  1549. }
  1550. return;
  1551. }
  1552. namespace {
  1553. class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
  1554. public:
  1555. bool shouldVisitTemplateInstantiations() const { return false; }
  1556. bool shouldWalkTypesOfTypeLocs() const { return false; }
  1557. bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
  1558. if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
  1559. if (E->getMethodFamily() == OMF_init)
  1560. return false;
  1561. }
  1562. return true;
  1563. }
  1564. };
  1565. } // anonymous namespace
  1566. static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
  1567. return !SuperInitChecker().TraverseStmt(MD->getBody());
  1568. }
  1569. void ObjCMigrateASTConsumer::inferDesignatedInitializers(
  1570. ASTContext &Ctx,
  1571. const ObjCImplementationDecl *ImplD) {
  1572. const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
  1573. if (!IFace || IFace->hasDesignatedInitializers())
  1574. return;
  1575. if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
  1576. return;
  1577. for (const auto *MD : ImplD->instance_methods()) {
  1578. if (MD->isDeprecated() ||
  1579. MD->getMethodFamily() != OMF_init ||
  1580. MD->isDesignatedInitializerForTheInterface())
  1581. continue;
  1582. const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
  1583. /*isInstance=*/true);
  1584. if (!IFaceM)
  1585. continue;
  1586. if (hasSuperInitCall(MD)) {
  1587. edit::Commit commit(*Editor);
  1588. commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER");
  1589. Editor->commit(commit);
  1590. }
  1591. }
  1592. }
  1593. bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
  1594. SourceLocation Loc) {
  1595. if (FoundationIncluded)
  1596. return true;
  1597. if (Loc.isInvalid())
  1598. return false;
  1599. edit::Commit commit(*Editor);
  1600. if (Ctx.getLangOpts().Modules)
  1601. commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
  1602. else
  1603. commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
  1604. Editor->commit(commit);
  1605. FoundationIncluded = true;
  1606. return true;
  1607. }
  1608. namespace {
  1609. class RewritesReceiver : public edit::EditsReceiver {
  1610. Rewriter &Rewrite;
  1611. public:
  1612. RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
  1613. void insert(SourceLocation loc, StringRef text) override {
  1614. Rewrite.InsertText(loc, text);
  1615. }
  1616. void replace(CharSourceRange range, StringRef text) override {
  1617. Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
  1618. }
  1619. };
  1620. class JSONEditWriter : public edit::EditsReceiver {
  1621. SourceManager &SourceMgr;
  1622. llvm::raw_ostream &OS;
  1623. public:
  1624. JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
  1625. : SourceMgr(SM), OS(OS) {
  1626. OS << "[\n";
  1627. }
  1628. ~JSONEditWriter() override { OS << "]\n"; }
  1629. private:
  1630. struct EntryWriter {
  1631. SourceManager &SourceMgr;
  1632. llvm::raw_ostream &OS;
  1633. EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
  1634. : SourceMgr(SM), OS(OS) {
  1635. OS << " {\n";
  1636. }
  1637. ~EntryWriter() {
  1638. OS << " },\n";
  1639. }
  1640. void writeLoc(SourceLocation Loc) {
  1641. FileID FID;
  1642. unsigned Offset;
  1643. std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
  1644. assert(!FID.isInvalid());
  1645. SmallString<200> Path =
  1646. StringRef(SourceMgr.getFileEntryForID(FID)->getName());
  1647. llvm::sys::fs::make_absolute(Path);
  1648. OS << " \"file\": \"";
  1649. OS.write_escaped(Path.str()) << "\",\n";
  1650. OS << " \"offset\": " << Offset << ",\n";
  1651. }
  1652. void writeRemove(CharSourceRange Range) {
  1653. assert(Range.isCharRange());
  1654. std::pair<FileID, unsigned> Begin =
  1655. SourceMgr.getDecomposedLoc(Range.getBegin());
  1656. std::pair<FileID, unsigned> End =
  1657. SourceMgr.getDecomposedLoc(Range.getEnd());
  1658. assert(Begin.first == End.first);
  1659. assert(Begin.second <= End.second);
  1660. unsigned Length = End.second - Begin.second;
  1661. OS << " \"remove\": " << Length << ",\n";
  1662. }
  1663. void writeText(StringRef Text) {
  1664. OS << " \"text\": \"";
  1665. OS.write_escaped(Text) << "\",\n";
  1666. }
  1667. };
  1668. void insert(SourceLocation Loc, StringRef Text) override {
  1669. EntryWriter Writer(SourceMgr, OS);
  1670. Writer.writeLoc(Loc);
  1671. Writer.writeText(Text);
  1672. }
  1673. void replace(CharSourceRange Range, StringRef Text) override {
  1674. EntryWriter Writer(SourceMgr, OS);
  1675. Writer.writeLoc(Range.getBegin());
  1676. Writer.writeRemove(Range);
  1677. Writer.writeText(Text);
  1678. }
  1679. void remove(CharSourceRange Range) override {
  1680. EntryWriter Writer(SourceMgr, OS);
  1681. Writer.writeLoc(Range.getBegin());
  1682. Writer.writeRemove(Range);
  1683. }
  1684. };
  1685. }
  1686. void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
  1687. TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
  1688. if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
  1689. for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
  1690. D != DEnd; ++D) {
  1691. FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
  1692. if (!FID.isInvalid())
  1693. if (!FileId.isInvalid() && FileId != FID) {
  1694. if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
  1695. AnnotateImplicitBridging(Ctx);
  1696. }
  1697. if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
  1698. if (canModify(CDecl))
  1699. migrateObjCContainerDecl(Ctx, CDecl);
  1700. if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
  1701. if (canModify(CatDecl))
  1702. migrateObjCContainerDecl(Ctx, CatDecl);
  1703. }
  1704. else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
  1705. ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
  1706. if (canModify(PDecl))
  1707. migrateObjCContainerDecl(Ctx, PDecl);
  1708. }
  1709. else if (const ObjCImplementationDecl *ImpDecl =
  1710. dyn_cast<ObjCImplementationDecl>(*D)) {
  1711. if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
  1712. canModify(ImpDecl))
  1713. migrateProtocolConformance(Ctx, ImpDecl);
  1714. }
  1715. else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
  1716. if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
  1717. continue;
  1718. if (!canModify(ED))
  1719. continue;
  1720. DeclContext::decl_iterator N = D;
  1721. if (++N != DEnd) {
  1722. const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
  1723. if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
  1724. D++;
  1725. }
  1726. else
  1727. migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
  1728. }
  1729. else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
  1730. if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
  1731. continue;
  1732. if (!canModify(TD))
  1733. continue;
  1734. DeclContext::decl_iterator N = D;
  1735. if (++N == DEnd)
  1736. continue;
  1737. if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
  1738. if (++N != DEnd)
  1739. if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
  1740. // prefer typedef-follows-enum to enum-follows-typedef pattern.
  1741. if (migrateNSEnumDecl(Ctx, ED, TDF)) {
  1742. ++D; ++D;
  1743. CacheObjCNSIntegerTypedefed(TD);
  1744. continue;
  1745. }
  1746. }
  1747. if (migrateNSEnumDecl(Ctx, ED, TD)) {
  1748. ++D;
  1749. continue;
  1750. }
  1751. }
  1752. CacheObjCNSIntegerTypedefed(TD);
  1753. }
  1754. else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
  1755. if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
  1756. canModify(FD))
  1757. migrateCFAnnotation(Ctx, FD);
  1758. }
  1759. if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
  1760. bool CanModify = canModify(CDecl);
  1761. // migrate methods which can have instancetype as their result type.
  1762. if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
  1763. CanModify)
  1764. migrateAllMethodInstaceType(Ctx, CDecl);
  1765. // annotate methods with CF annotations.
  1766. if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
  1767. CanModify)
  1768. migrateARCSafeAnnotation(Ctx, CDecl);
  1769. }
  1770. if (const ObjCImplementationDecl *
  1771. ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
  1772. if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
  1773. canModify(ImplD))
  1774. inferDesignatedInitializers(Ctx, ImplD);
  1775. }
  1776. }
  1777. if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
  1778. AnnotateImplicitBridging(Ctx);
  1779. }
  1780. if (IsOutputFile) {
  1781. std::error_code EC;
  1782. llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
  1783. if (EC) {
  1784. DiagnosticsEngine &Diags = Ctx.getDiagnostics();
  1785. Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
  1786. << EC.message();
  1787. return;
  1788. }
  1789. JSONEditWriter Writer(Ctx.getSourceManager(), OS);
  1790. Editor->applyRewrites(Writer);
  1791. return;
  1792. }
  1793. Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
  1794. RewritesReceiver Rec(rewriter);
  1795. Editor->applyRewrites(Rec);
  1796. for (Rewriter::buffer_iterator
  1797. I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
  1798. FileID FID = I->first;
  1799. RewriteBuffer &buf = I->second;
  1800. const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
  1801. assert(file);
  1802. SmallString<512> newText;
  1803. llvm::raw_svector_ostream vecOS(newText);
  1804. buf.write(vecOS);
  1805. vecOS.flush();
  1806. std::unique_ptr<llvm::MemoryBuffer> memBuf(
  1807. llvm::MemoryBuffer::getMemBufferCopy(
  1808. StringRef(newText.data(), newText.size()), file->getName()));
  1809. SmallString<64> filePath(file->getName());
  1810. FileMgr.FixupRelativePath(filePath);
  1811. Remapper.remap(filePath.str(), std::move(memBuf));
  1812. }
  1813. if (IsOutputFile) {
  1814. Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
  1815. } else {
  1816. Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
  1817. }
  1818. }
  1819. bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
  1820. CI.getDiagnostics().setIgnoreAllWarnings(true);
  1821. return true;
  1822. }
  1823. static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
  1824. using namespace llvm::sys::fs;
  1825. using namespace llvm::sys::path;
  1826. std::vector<std::string> Filenames;
  1827. if (DirPath.empty() || !is_directory(DirPath))
  1828. return Filenames;
  1829. std::error_code EC;
  1830. directory_iterator DI = directory_iterator(DirPath, EC);
  1831. directory_iterator DE;
  1832. for (; !EC && DI != DE; DI = DI.increment(EC)) {
  1833. if (is_regular_file(DI->path()))
  1834. Filenames.push_back(filename(DI->path()));
  1835. }
  1836. return Filenames;
  1837. }
  1838. std::unique_ptr<ASTConsumer>
  1839. MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  1840. PPConditionalDirectiveRecord *
  1841. PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
  1842. unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
  1843. unsigned ObjCMTOpts = ObjCMTAction;
  1844. // These are companion flags, they do not enable transformations.
  1845. ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
  1846. FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty);
  1847. if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
  1848. // If no specific option was given, enable literals+subscripting transforms
  1849. // by default.
  1850. ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
  1851. FrontendOptions::ObjCMT_Subscripting;
  1852. }
  1853. CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
  1854. std::vector<std::string> WhiteList =
  1855. getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath);
  1856. return llvm::make_unique<ObjCMigrateASTConsumer>(
  1857. CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
  1858. CI.getFileManager(), PPRec, CI.getPreprocessor(),
  1859. /*isOutputFile=*/true, WhiteList);
  1860. }
  1861. namespace {
  1862. struct EditEntry {
  1863. const FileEntry *File;
  1864. unsigned Offset;
  1865. unsigned RemoveLen;
  1866. std::string Text;
  1867. EditEntry() : File(), Offset(), RemoveLen() {}
  1868. };
  1869. }
  1870. namespace llvm {
  1871. template<> struct DenseMapInfo<EditEntry> {
  1872. static inline EditEntry getEmptyKey() {
  1873. EditEntry Entry;
  1874. Entry.Offset = unsigned(-1);
  1875. return Entry;
  1876. }
  1877. static inline EditEntry getTombstoneKey() {
  1878. EditEntry Entry;
  1879. Entry.Offset = unsigned(-2);
  1880. return Entry;
  1881. }
  1882. static unsigned getHashValue(const EditEntry& Val) {
  1883. llvm::FoldingSetNodeID ID;
  1884. ID.AddPointer(Val.File);
  1885. ID.AddInteger(Val.Offset);
  1886. ID.AddInteger(Val.RemoveLen);
  1887. ID.AddString(Val.Text);
  1888. return ID.ComputeHash();
  1889. }
  1890. static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
  1891. return LHS.File == RHS.File &&
  1892. LHS.Offset == RHS.Offset &&
  1893. LHS.RemoveLen == RHS.RemoveLen &&
  1894. LHS.Text == RHS.Text;
  1895. }
  1896. };
  1897. }
  1898. namespace {
  1899. class RemapFileParser {
  1900. FileManager &FileMgr;
  1901. public:
  1902. RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }
  1903. bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
  1904. using namespace llvm::yaml;
  1905. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
  1906. llvm::MemoryBuffer::getFile(File);
  1907. if (!FileBufOrErr)
  1908. return true;
  1909. llvm::SourceMgr SM;
  1910. Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
  1911. document_iterator I = YAMLStream.begin();
  1912. if (I == YAMLStream.end())
  1913. return true;
  1914. Node *Root = I->getRoot();
  1915. if (!Root)
  1916. return true;
  1917. SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
  1918. if (!SeqNode)
  1919. return true;
  1920. for (SequenceNode::iterator
  1921. AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
  1922. MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
  1923. if (!MapNode)
  1924. continue;
  1925. parseEdit(MapNode, Entries);
  1926. }
  1927. return false;
  1928. }
  1929. private:
  1930. void parseEdit(llvm::yaml::MappingNode *Node,
  1931. SmallVectorImpl<EditEntry> &Entries) {
  1932. using namespace llvm::yaml;
  1933. EditEntry Entry;
  1934. bool Ignore = false;
  1935. for (MappingNode::iterator
  1936. KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
  1937. ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
  1938. if (!KeyString)
  1939. continue;
  1940. SmallString<10> KeyStorage;
  1941. StringRef Key = KeyString->getValue(KeyStorage);
  1942. ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
  1943. if (!ValueString)
  1944. continue;
  1945. SmallString<64> ValueStorage;
  1946. StringRef Val = ValueString->getValue(ValueStorage);
  1947. if (Key == "file") {
  1948. const FileEntry *FE = FileMgr.getFile(Val);
  1949. if (!FE)
  1950. Ignore = true;
  1951. Entry.File = FE;
  1952. } else if (Key == "offset") {
  1953. if (Val.getAsInteger(10, Entry.Offset))
  1954. Ignore = true;
  1955. } else if (Key == "remove") {
  1956. if (Val.getAsInteger(10, Entry.RemoveLen))
  1957. Ignore = true;
  1958. } else if (Key == "text") {
  1959. Entry.Text = Val;
  1960. }
  1961. }
  1962. if (!Ignore)
  1963. Entries.push_back(Entry);
  1964. }
  1965. };
  1966. }
  1967. static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
  1968. Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
  1969. << Err.str();
  1970. return true;
  1971. }
  1972. static std::string applyEditsToTemp(const FileEntry *FE,
  1973. ArrayRef<EditEntry> Edits,
  1974. FileManager &FileMgr,
  1975. DiagnosticsEngine &Diag) {
  1976. using namespace llvm::sys;
  1977. SourceManager SM(Diag, FileMgr);
  1978. FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
  1979. LangOptions LangOpts;
  1980. edit::EditedSource Editor(SM, LangOpts);
  1981. for (ArrayRef<EditEntry>::iterator
  1982. I = Edits.begin(), E = Edits.end(); I != E; ++I) {
  1983. const EditEntry &Entry = *I;
  1984. assert(Entry.File == FE);
  1985. SourceLocation Loc =
  1986. SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
  1987. CharSourceRange Range;
  1988. if (Entry.RemoveLen != 0) {
  1989. Range = CharSourceRange::getCharRange(Loc,
  1990. Loc.getLocWithOffset(Entry.RemoveLen));
  1991. }
  1992. edit::Commit commit(Editor);
  1993. if (Range.isInvalid()) {
  1994. commit.insert(Loc, Entry.Text);
  1995. } else if (Entry.Text.empty()) {
  1996. commit.remove(Range);
  1997. } else {
  1998. commit.replace(Range, Entry.Text);
  1999. }
  2000. Editor.commit(commit);
  2001. }
  2002. Rewriter rewriter(SM, LangOpts);
  2003. RewritesReceiver Rec(rewriter);
  2004. Editor.applyRewrites(Rec);
  2005. const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
  2006. SmallString<512> NewText;
  2007. llvm::raw_svector_ostream OS(NewText);
  2008. Buf->write(OS);
  2009. OS.flush();
  2010. SmallString<64> TempPath;
  2011. int FD;
  2012. if (fs::createTemporaryFile(path::filename(FE->getName()),
  2013. path::extension(FE->getName()), FD,
  2014. TempPath)) {
  2015. reportDiag("Could not create file: " + TempPath.str(), Diag);
  2016. return std::string();
  2017. }
  2018. llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
  2019. TmpOut.write(NewText.data(), NewText.size());
  2020. TmpOut.close();
  2021. return TempPath.str();
  2022. }
  2023. bool arcmt::getFileRemappingsFromFileList(
  2024. std::vector<std::pair<std::string,std::string> > &remap,
  2025. ArrayRef<StringRef> remapFiles,
  2026. DiagnosticConsumer *DiagClient) {
  2027. bool hasErrorOccurred = false;
  2028. FileSystemOptions FSOpts;
  2029. FileManager FileMgr(FSOpts);
  2030. RemapFileParser Parser(FileMgr);
  2031. IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  2032. IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
  2033. new DiagnosticsEngine(DiagID, new DiagnosticOptions,
  2034. DiagClient, /*ShouldOwnClient=*/false));
  2035. typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
  2036. FileEditEntriesTy;
  2037. FileEditEntriesTy FileEditEntries;
  2038. llvm::DenseSet<EditEntry> EntriesSet;
  2039. for (ArrayRef<StringRef>::iterator
  2040. I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
  2041. SmallVector<EditEntry, 16> Entries;
  2042. if (Parser.parse(*I, Entries))
  2043. continue;
  2044. for (SmallVectorImpl<EditEntry>::iterator
  2045. EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
  2046. EditEntry &Entry = *EI;
  2047. if (!Entry.File)
  2048. continue;
  2049. std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
  2050. Insert = EntriesSet.insert(Entry);
  2051. if (!Insert.second)
  2052. continue;
  2053. FileEditEntries[Entry.File].push_back(Entry);
  2054. }
  2055. }
  2056. for (FileEditEntriesTy::iterator
  2057. I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
  2058. std::string TempFile = applyEditsToTemp(I->first, I->second,
  2059. FileMgr, *Diags);
  2060. if (TempFile.empty()) {
  2061. hasErrorOccurred = true;
  2062. continue;
  2063. }
  2064. remap.emplace_back(I->first->getName(), TempFile);
  2065. }
  2066. return hasErrorOccurred;
  2067. }