ObjCMT.cpp 82 KB

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