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