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