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