ObjCMT.cpp 82 KB

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