ObjCMT.cpp 82 KB

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