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