ObjCMT.cpp 76 KB

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