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