//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Transforms.h"
#include "clang/Analysis/RetainSummaryManager.h"
#include "clang/ARCMigrate/ARCMT.h"
#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/NSAPI.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Edit/Rewriters.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"

using namespace clang;
using namespace arcmt;
using namespace ento;

namespace {

class ObjCMigrateASTConsumer : public ASTConsumer {
  enum CF_BRIDGING_KIND {
    CF_BRIDGING_NONE,
    CF_BRIDGING_ENABLE,
    CF_BRIDGING_MAY_INCLUDE
  };

  void migrateDecl(Decl *D);
  void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
  void migrateProtocolConformance(ASTContext &Ctx,
                                  const ObjCImplementationDecl *ImpDecl);
  void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
  bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
                     const TypedefDecl *TypedefDcl);
  void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
  void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
                                 ObjCMethodDecl *OM);
  bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
  void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
  void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
  void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
                            ObjCMethodDecl *OM,
                            ObjCInstanceTypeFamily OIT_Family = OIT_None);

  void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
  void AddCFAnnotations(ASTContext &Ctx,
                        const RetainSummary *RS,
                        const FunctionDecl *FuncDecl, bool ResultAnnotated);
  void AddCFAnnotations(ASTContext &Ctx,
                        const RetainSummary *RS,
                        const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);

  void AnnotateImplicitBridging(ASTContext &Ctx);

  CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
                                                const FunctionDecl *FuncDecl);

  void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);

  void migrateAddMethodAnnotation(ASTContext &Ctx,
                                  const ObjCMethodDecl *MethodDecl);

  void inferDesignatedInitializers(ASTContext &Ctx,
                                   const ObjCImplementationDecl *ImplD);

  bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);

  std::unique_ptr<RetainSummaryManager> Summaries;

public:
  std::string MigrateDir;
  unsigned ASTMigrateActions;
  FileID FileId;
  const TypedefDecl *NSIntegerTypedefed;
  const TypedefDecl *NSUIntegerTypedefed;
  std::unique_ptr<NSAPI> NSAPIObj;
  std::unique_ptr<edit::EditedSource> Editor;
  FileRemapper &Remapper;
  FileManager &FileMgr;
  const PPConditionalDirectiveRecord *PPRec;
  Preprocessor &PP;
  bool IsOutputFile;
  bool FoundationIncluded;
  llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
  llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
  llvm::StringSet<> WhiteListFilenames;

  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) {
    if (!Summaries)
      Summaries.reset(new RetainSummaryManager(Ctx,
                                               /*TrackNSCFObjects=*/true,
                                               /*trackOSObjects=*/false));
    return *Summaries;
  }

  ObjCMigrateASTConsumer(StringRef migrateDir,
                         unsigned astMigrateActions,
                         FileRemapper &remapper,
                         FileManager &fileMgr,
                         const PPConditionalDirectiveRecord *PPRec,
                         Preprocessor &PP,
                         bool isOutputFile,
                         ArrayRef<std::string> WhiteList)
  : MigrateDir(migrateDir),
    ASTMigrateActions(astMigrateActions),
    NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
    Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
    IsOutputFile(isOutputFile),
    FoundationIncluded(false){

    // FIXME: StringSet should have insert(iter, iter) to use here.
    for (const std::string &Val : WhiteList)
      WhiteListFilenames.insert(Val);
  }

protected:
  void Initialize(ASTContext &Context) override {
    NSAPIObj.reset(new NSAPI(Context));
    Editor.reset(new edit::EditedSource(Context.getSourceManager(),
                                        Context.getLangOpts(),
                                        PPRec));
  }

  bool HandleTopLevelDecl(DeclGroupRef DG) override {
    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
      migrateDecl(*I);
    return true;
  }
  void HandleInterestingDecl(DeclGroupRef DG) override {
    // Ignore decls from the PCH.
  }
  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
    ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
  }

  void HandleTranslationUnit(ASTContext &Ctx) override;

  bool canModifyFile(StringRef Path) {
    if (WhiteListFilenames.empty())
      return true;
    return WhiteListFilenames.find(llvm::sys::path::filename(Path))
        != WhiteListFilenames.end();
  }
  bool canModifyFile(const FileEntry *FE) {
    if (!FE)
      return false;
    return canModifyFile(FE->getName());
  }
  bool canModifyFile(FileID FID) {
    if (FID.isInvalid())
      return false;
    return canModifyFile(PP.getSourceManager().getFileEntryForID(FID));
  }

  bool canModify(const Decl *D) {
    if (!D)
      return false;
    if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D))
      return canModify(CatImpl->getCategoryDecl());
    if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D))
      return canModify(Impl->getClassInterface());
    if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
      return canModify(cast<Decl>(MD->getDeclContext()));

    FileID FID = PP.getSourceManager().getFileID(D->getLocation());
    return canModifyFile(FID);
  }
};

} // end anonymous namespace

ObjCMigrateAction::ObjCMigrateAction(
                                  std::unique_ptr<FrontendAction> WrappedAction,
                                     StringRef migrateDir,
                                     unsigned migrateAction)
  : WrapperFrontendAction(std::move(WrappedAction)), MigrateDir(migrateDir),
    ObjCMigAction(migrateAction),
    CompInst(nullptr) {
  if (MigrateDir.empty())
    MigrateDir = "."; // user current directory if none is given.
}

std::unique_ptr<ASTConsumer>
ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  PPConditionalDirectiveRecord *
    PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
  CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
  Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile));
  Consumers.push_back(std::make_unique<ObjCMigrateASTConsumer>(
      MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
      CompInst->getPreprocessor(), false, None));
  return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}

bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
                        /*ignoreIfFilesChanged=*/true);
  CompInst = &CI;
  CI.getDiagnostics().setIgnoreAllWarnings(true);
  return true;
}

namespace {
  // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
  bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
    const Expr* Expr = FullExpr->IgnoreImpCasts();
    return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
             isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
             isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
             isa<CXXTypeidExpr>(Expr) ||
             isa<CXXUnresolvedConstructExpr>(Expr) ||
             isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
             isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
             isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
             isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
  }

  /// - Rewrite message expression for Objective-C setter and getters into
  /// property-dot syntax.
  bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
                                  Preprocessor &PP,
                                  const NSAPI &NS, edit::Commit &commit,
                                  const ParentMap *PMap) {
    if (!Msg || Msg->isImplicit() ||
        (Msg->getReceiverKind() != ObjCMessageExpr::Instance &&
         Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance))
      return false;
    if (const Expr *Receiver = Msg->getInstanceReceiver())
      if (Receiver->getType()->isObjCBuiltinType())
        return false;

    const ObjCMethodDecl *Method = Msg->getMethodDecl();
    if (!Method)
      return false;
    if (!Method->isPropertyAccessor())
      return false;

    const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
    if (!Prop)
      return false;

    SourceRange MsgRange = Msg->getSourceRange();
    bool ReceiverIsSuper =
      (Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
    // for 'super' receiver is nullptr.
    const Expr *receiver = Msg->getInstanceReceiver();
    bool NeedsParen =
      ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver);
    bool IsGetter = (Msg->getNumArgs() == 0);
    if (IsGetter) {
      // Find space location range between receiver expression and getter method.
      SourceLocation BegLoc =
          ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
      BegLoc = PP.getLocForEndOfToken(BegLoc);
      SourceLocation EndLoc = Msg->getSelectorLoc(0);
      SourceRange SpaceRange(BegLoc, EndLoc);
      std::string PropertyDotString;
      // rewrite getter method expression into: receiver.property or
      // (receiver).property
      if (NeedsParen) {
        commit.insertBefore(receiver->getBeginLoc(), "(");
        PropertyDotString = ").";
      }
      else
        PropertyDotString = ".";
      PropertyDotString += Prop->getName();
      commit.replace(SpaceRange, PropertyDotString);

      // remove '[' ']'
      commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
      commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
    } else {
      if (NeedsParen)
        commit.insertWrap("(", receiver->getSourceRange(), ")");
      std::string PropertyDotString = ".";
      PropertyDotString += Prop->getName();
      PropertyDotString += " =";
      const Expr*const* Args = Msg->getArgs();
      const Expr *RHS = Args[0];
      if (!RHS)
        return false;
      SourceLocation BegLoc =
          ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
      BegLoc = PP.getLocForEndOfToken(BegLoc);
      SourceLocation EndLoc = RHS->getBeginLoc();
      EndLoc = EndLoc.getLocWithOffset(-1);
      const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
      // Add a space after '=' if there is no space between RHS and '='
      if (colon && colon[0] == ':')
        PropertyDotString += " ";
      SourceRange Range(BegLoc, EndLoc);
      commit.replace(Range, PropertyDotString);
      // remove '[' ']'
      commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
      commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
    }
    return true;
  }

class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
  ObjCMigrateASTConsumer &Consumer;
  ParentMap &PMap;

public:
  ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
    : Consumer(consumer), PMap(PMap) { }

  bool shouldVisitTemplateInstantiations() const { return false; }
  bool shouldWalkTypesOfTypeLocs() const { return false; }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
      edit::Commit commit(*Consumer.Editor);
      edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
      Consumer.Editor->commit(commit);
    }

    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
      edit::Commit commit(*Consumer.Editor);
      edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
      Consumer.Editor->commit(commit);
    }

    if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
      edit::Commit commit(*Consumer.Editor);
      rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
                                 commit, &PMap);
      Consumer.Editor->commit(commit);
    }

    return true;
  }

  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
    // Do depth first; we want to rewrite the subexpressions first so that if
    // we have to move expressions we will move them already rewritten.
    for (Stmt *SubStmt : E->children())
      if (!TraverseStmt(SubStmt))
        return false;

    return WalkUpFromObjCMessageExpr(E);
  }
};

class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
  ObjCMigrateASTConsumer &Consumer;
  std::unique_ptr<ParentMap> PMap;

public:
  BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }

  bool shouldVisitTemplateInstantiations() const { return false; }
  bool shouldWalkTypesOfTypeLocs() const { return false; }

  bool TraverseStmt(Stmt *S) {
    PMap.reset(new ParentMap(S));
    ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
    return true;
  }
};
} // end anonymous namespace

void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
  if (!D)
    return;
  if (isa<ObjCMethodDecl>(D))
    return; // Wait for the ObjC container declaration.

  BodyMigrator(*this).TraverseDecl(D);
}

static void append_attr(std::string &PropertyString, const char *attr,
                        bool &LParenAdded) {
  if (!LParenAdded) {
    PropertyString += "(";
    LParenAdded = true;
  }
  else
    PropertyString += ", ";
  PropertyString += attr;
}

static
void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
                                               const std::string& TypeString,
                                               const char *name) {
  const char *argPtr = TypeString.c_str();
  int paren = 0;
  while (*argPtr) {
    switch (*argPtr) {
      case '(':
        PropertyString += *argPtr;
        paren++;
        break;
      case ')':
        PropertyString += *argPtr;
        paren--;
        break;
      case '^':
      case '*':
        PropertyString += (*argPtr);
        if (paren == 1) {
          PropertyString += name;
          name = "";
        }
        break;
      default:
        PropertyString += *argPtr;
        break;
    }
    argPtr++;
  }
}

static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
  Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
  bool RetainableObject = ArgType->isObjCRetainableType();
  if (RetainableObject &&
      (propertyLifetime == Qualifiers::OCL_Strong
       || propertyLifetime == Qualifiers::OCL_None)) {
    if (const ObjCObjectPointerType *ObjPtrTy =
        ArgType->getAs<ObjCObjectPointerType>()) {
      ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
      if (IDecl &&
          IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
        return "copy";
      else
        return "strong";
    }
    else if (ArgType->isBlockPointerType())
      return "copy";
  } else if (propertyLifetime == Qualifiers::OCL_Weak)
    // TODO. More precise determination of 'weak' attribute requires
    // looking into setter's implementation for backing weak ivar.
    return "weak";
  else if (RetainableObject)
    return ArgType->isBlockPointerType() ? "copy" : "strong";
  return nullptr;
}

static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
                                  const ObjCMethodDecl *Setter,
                                  const NSAPI &NS, edit::Commit &commit,
                                  unsigned LengthOfPrefix,
                                  bool Atomic, bool UseNsIosOnlyMacro,
                                  bool AvailabilityArgsMatch) {
  ASTContext &Context = NS.getASTContext();
  bool LParenAdded = false;
  std::string PropertyString = "@property ";
  if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {
    PropertyString += "(NS_NONATOMIC_IOSONLY";
    LParenAdded = true;
  } else if (!Atomic) {
    PropertyString += "(nonatomic";
    LParenAdded = true;
  }

  std::string PropertyNameString = Getter->getNameAsString();
  StringRef PropertyName(PropertyNameString);
  if (LengthOfPrefix > 0) {
    if (!LParenAdded) {
      PropertyString += "(getter=";
      LParenAdded = true;
    }
    else
      PropertyString += ", getter=";
    PropertyString += PropertyNameString;
  }
  // Property with no setter may be suggested as a 'readonly' property.
  if (!Setter)
    append_attr(PropertyString, "readonly", LParenAdded);


  // Short circuit 'delegate' properties that contain the name "delegate" or
  // "dataSource", or have exact name "target" to have 'assign' attribute.
  if (PropertyName.equals("target") ||
      (PropertyName.find("delegate") != StringRef::npos) ||
      (PropertyName.find("dataSource") != StringRef::npos)) {
    QualType QT = Getter->getReturnType();
    if (!QT->isRealType())
      append_attr(PropertyString, "assign", LParenAdded);
  } else if (!Setter) {
    QualType ResType = Context.getCanonicalType(Getter->getReturnType());
    if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
      append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
  } else {
    const ParmVarDecl *argDecl = *Setter->param_begin();
    QualType ArgType = Context.getCanonicalType(argDecl->getType());
    if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
      append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
  }
  if (LParenAdded)
    PropertyString += ')';
  QualType RT = Getter->getReturnType();
  if (!isa<TypedefType>(RT)) {
    // strip off any ARC lifetime qualifier.
    QualType CanResultTy = Context.getCanonicalType(RT);
    if (CanResultTy.getQualifiers().hasObjCLifetime()) {
      Qualifiers Qs = CanResultTy.getQualifiers();
      Qs.removeObjCLifetime();
      RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
    }
  }
  PropertyString += " ";
  PrintingPolicy SubPolicy(Context.getPrintingPolicy());
  SubPolicy.SuppressStrongLifetime = true;
  SubPolicy.SuppressLifetimeQualifiers = true;
  std::string TypeString = RT.getAsString(SubPolicy);
  if (LengthOfPrefix > 0) {
    // property name must strip off "is" and lower case the first character
    // after that; e.g. isContinuous will become continuous.
    StringRef PropertyNameStringRef(PropertyNameString);
    PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
    PropertyNameString = PropertyNameStringRef;
    bool NoLowering = (isUppercase(PropertyNameString[0]) &&
                       PropertyNameString.size() > 1 &&
                       isUppercase(PropertyNameString[1]));
    if (!NoLowering)
      PropertyNameString[0] = toLowercase(PropertyNameString[0]);
  }
  if (RT->isBlockPointerType() || RT->isFunctionPointerType())
    MigrateBlockOrFunctionPointerTypeVariable(PropertyString,
                                              TypeString,
                                              PropertyNameString.c_str());
  else {
    char LastChar = TypeString[TypeString.size()-1];
    PropertyString += TypeString;
    if (LastChar != '*')
      PropertyString += ' ';
    PropertyString += PropertyNameString;
  }
  SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
  Selector GetterSelector = Getter->getSelector();

  SourceLocation EndGetterSelectorLoc =
    StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
  commit.replace(CharSourceRange::getCharRange(Getter->getBeginLoc(),
                                               EndGetterSelectorLoc),
                 PropertyString);
  if (Setter && AvailabilityArgsMatch) {
    SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
    // Get location past ';'
    EndLoc = EndLoc.getLocWithOffset(1);
    SourceLocation BeginOfSetterDclLoc = Setter->getBeginLoc();
    // FIXME. This assumes that setter decl; is immediately preceded by eoln.
    // It is trying to remove the setter method decl. line entirely.
    BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
    commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
  }
}

static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) {
  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) {
    StringRef Name = CatDecl->getName();
    return Name.endswith("Deprecated");
  }
  return false;
}

void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
                                                      ObjCContainerDecl *D) {
  if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
    return;

  for (auto *Method : D->methods()) {
    if (Method->isDeprecated())
      continue;
    bool PropertyInferred = migrateProperty(Ctx, D, Method);
    // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
    // the getter method as it ends up on the property itself which we don't want
    // to do unless -objcmt-returns-innerpointer-property  option is on.
    if (!PropertyInferred ||
        (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
      if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
        migrateNsReturnsInnerPointer(Ctx, Method);
  }
  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
    return;

  for (auto *Prop : D->instance_properties()) {
    if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
        !Prop->isDeprecated())
      migratePropertyNsReturnsInnerPointer(Ctx, Prop);
  }
}

static bool
ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
                                      const ObjCImplementationDecl *ImpDecl,
                                       const ObjCInterfaceDecl *IDecl,
                                      ObjCProtocolDecl *Protocol) {
  // In auto-synthesis, protocol properties are not synthesized. So,
  // a conforming protocol must have its required properties declared
  // in class interface.
  bool HasAtleastOneRequiredProperty = false;
  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
    for (const auto *Property : PDecl->instance_properties()) {
      if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
        continue;
      HasAtleastOneRequiredProperty = true;
      DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
      if (R.size() == 0) {
        // Relax the rule and look into class's implementation for a synthesize
        // or dynamic declaration. Class is implementing a property coming from
        // another protocol. This still makes the target protocol as conforming.
        if (!ImpDecl->FindPropertyImplDecl(
                                  Property->getDeclName().getAsIdentifierInfo(),
                                  Property->getQueryKind()))
          return false;
      }
      else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
          if ((ClassProperty->getPropertyAttributes()
              != Property->getPropertyAttributes()) ||
              !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
            return false;
      }
      else
        return false;
    }

  // At this point, all required properties in this protocol conform to those
  // declared in the class.
  // Check that class implements the required methods of the protocol too.
  bool HasAtleastOneRequiredMethod = false;
  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
    if (PDecl->meth_begin() == PDecl->meth_end())
      return HasAtleastOneRequiredProperty;
    for (const auto *MD : PDecl->methods()) {
      if (MD->isImplicit())
        continue;
      if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
        continue;
      DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
      if (R.size() == 0)
        return false;
      bool match = false;
      HasAtleastOneRequiredMethod = true;
      for (unsigned I = 0, N = R.size(); I != N; ++I)
        if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
          if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
            match = true;
            break;
          }
      if (!match)
        return false;
    }
  }
  return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
}

static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
                    llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
                    const NSAPI &NS, edit::Commit &commit) {
  const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
  std::string ClassString;
  SourceLocation EndLoc =
  IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();

  if (Protocols.empty()) {
    ClassString = '<';
    for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
      ClassString += ConformingProtocols[i]->getNameAsString();
      if (i != (e-1))
        ClassString += ", ";
    }
    ClassString += "> ";
  }
  else {
    ClassString = ", ";
    for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
      ClassString += ConformingProtocols[i]->getNameAsString();
      if (i != (e-1))
        ClassString += ", ";
    }
    ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
    EndLoc = *PL;
  }

  commit.insertAfterToken(EndLoc, ClassString);
  return true;
}

static StringRef GetUnsignedName(StringRef NSIntegerName) {
  StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
    .Case("int8_t", "uint8_t")
    .Case("int16_t", "uint16_t")
    .Case("int32_t", "uint32_t")
    .Case("NSInteger", "NSUInteger")
    .Case("int64_t", "uint64_t")
    .Default(NSIntegerName);
  return UnsignedName;
}

static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
                                const TypedefDecl *TypedefDcl,
                                const NSAPI &NS, edit::Commit &commit,
                                StringRef NSIntegerName,
                                bool NSOptions) {
  std::string ClassString;
  if (NSOptions) {
    ClassString = "typedef NS_OPTIONS(";
    ClassString += GetUnsignedName(NSIntegerName);
  }
  else {
    ClassString = "typedef NS_ENUM(";
    ClassString += NSIntegerName;
  }
  ClassString += ", ";

  ClassString += TypedefDcl->getIdentifier()->getName();
  ClassString += ')';
  SourceRange R(EnumDcl->getBeginLoc(), EnumDcl->getBeginLoc());
  commit.replace(R, ClassString);
  SourceLocation EndOfEnumDclLoc = EnumDcl->getEndLoc();
  EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
                                                 NS.getASTContext(), /*IsDecl*/true);
  if (EndOfEnumDclLoc.isValid()) {
    SourceRange EnumDclRange(EnumDcl->getBeginLoc(), EndOfEnumDclLoc);
    commit.insertFromRange(TypedefDcl->getBeginLoc(), EnumDclRange);
  }
  else
    return false;

  SourceLocation EndTypedefDclLoc = TypedefDcl->getEndLoc();
  EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
                                                 NS.getASTContext(), /*IsDecl*/true);
  if (EndTypedefDclLoc.isValid()) {
    SourceRange TDRange(TypedefDcl->getBeginLoc(), EndTypedefDclLoc);
    commit.remove(TDRange);
  }
  else
    return false;

  EndOfEnumDclLoc =
      trans::findLocationAfterSemi(EnumDcl->getEndLoc(), NS.getASTContext(),
                                   /*IsDecl*/ true);
  if (EndOfEnumDclLoc.isValid()) {
    SourceLocation BeginOfEnumDclLoc = EnumDcl->getBeginLoc();
    // FIXME. This assumes that enum decl; is immediately preceded by eoln.
    // It is trying to remove the enum decl. lines entirely.
    BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
    commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
    return true;
  }
  return false;
}

static void rewriteToNSMacroDecl(ASTContext &Ctx,
                                 const EnumDecl *EnumDcl,
                                const TypedefDecl *TypedefDcl,
                                const NSAPI &NS, edit::Commit &commit,
                                 bool IsNSIntegerType) {
  QualType DesignatedEnumType = EnumDcl->getIntegerType();
  assert(!DesignatedEnumType.isNull()
         && "rewriteToNSMacroDecl - underlying enum type is null");

  PrintingPolicy Policy(Ctx.getPrintingPolicy());
  std::string TypeString = DesignatedEnumType.getAsString(Policy);
  std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
  ClassString += TypeString;
  ClassString += ", ";

  ClassString += TypedefDcl->getIdentifier()->getName();
  ClassString += ") ";
  SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
  if (EndLoc.isInvalid())
    return;
  CharSourceRange R =
      CharSourceRange::getCharRange(EnumDcl->getBeginLoc(), EndLoc);
  commit.replace(R, ClassString);
  // This is to remove spaces between '}' and typedef name.
  SourceLocation StartTypedefLoc = EnumDcl->getEndLoc();
  StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
  SourceLocation EndTypedefLoc = TypedefDcl->getEndLoc();

  commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
}

static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
                              const EnumDecl *EnumDcl) {
  bool PowerOfTwo = true;
  bool AllHexdecimalEnumerator = true;
  uint64_t MaxPowerOfTwoVal = 0;
  for (auto Enumerator : EnumDcl->enumerators()) {
    const Expr *InitExpr = Enumerator->getInitExpr();
    if (!InitExpr) {
      PowerOfTwo = false;
      AllHexdecimalEnumerator = false;
      continue;
    }
    InitExpr = InitExpr->IgnoreParenCasts();
    if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
      if (BO->isShiftOp() || BO->isBitwiseOp())
        return true;

    uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
    if (PowerOfTwo && EnumVal) {
      if (!llvm::isPowerOf2_64(EnumVal))
        PowerOfTwo = false;
      else if (EnumVal > MaxPowerOfTwoVal)
        MaxPowerOfTwoVal = EnumVal;
    }
    if (AllHexdecimalEnumerator && EnumVal) {
      bool FoundHexdecimalEnumerator = false;
      SourceLocation EndLoc = Enumerator->getEndLoc();
      Token Tok;
      if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
        if (Tok.isLiteral() && Tok.getLength() > 2) {
          if (const char *StringLit = Tok.getLiteralData())
            FoundHexdecimalEnumerator =
              (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
        }
      if (!FoundHexdecimalEnumerator)
        AllHexdecimalEnumerator = false;
    }
  }
  return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
}

void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
                                            const ObjCImplementationDecl *ImpDecl) {
  const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
  if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
    return;
  // Find all implicit conforming protocols for this class
  // and make them explicit.
  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
  Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
  llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;

  for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
    if (!ExplicitProtocols.count(ProtDecl))
      PotentialImplicitProtocols.push_back(ProtDecl);

  if (PotentialImplicitProtocols.empty())
    return;

  // go through list of non-optional methods and properties in each protocol
  // in the PotentialImplicitProtocols list. If class implements every one of the
  // methods and properties, then this class conforms to this protocol.
  llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
  for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
    if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
                                              PotentialImplicitProtocols[i]))
      ConformingProtocols.push_back(PotentialImplicitProtocols[i]);

  if (ConformingProtocols.empty())
    return;

  // Further reduce number of conforming protocols. If protocol P1 is in the list
  // protocol P2 (P2<P1>), No need to include P1.
  llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
  for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
    bool DropIt = false;
    ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
    for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
      ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
      if (PDecl == TargetPDecl)
        continue;
      if (PDecl->lookupProtocolNamed(
            TargetPDecl->getDeclName().getAsIdentifierInfo())) {
        DropIt = true;
        break;
      }
    }
    if (!DropIt)
      MinimalConformingProtocols.push_back(TargetPDecl);
  }
  if (MinimalConformingProtocols.empty())
    return;
  edit::Commit commit(*Editor);
  rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
                             *NSAPIObj, commit);
  Editor->commit(commit);
}

void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
                                          const TypedefDecl *TypedefDcl) {

  QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
  if (NSAPIObj->isObjCNSIntegerType(qt))
    NSIntegerTypedefed = TypedefDcl;
  else if (NSAPIObj->isObjCNSUIntegerType(qt))
    NSUIntegerTypedefed = TypedefDcl;
}

bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
                                           const EnumDecl *EnumDcl,
                                           const TypedefDecl *TypedefDcl) {
  if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
      EnumDcl->isDeprecated())
    return false;
  if (!TypedefDcl) {
    if (NSIntegerTypedefed) {
      TypedefDcl = NSIntegerTypedefed;
      NSIntegerTypedefed = nullptr;
    }
    else if (NSUIntegerTypedefed) {
      TypedefDcl = NSUIntegerTypedefed;
      NSUIntegerTypedefed = nullptr;
    }
    else
      return false;
    FileID FileIdOfTypedefDcl =
      PP.getSourceManager().getFileID(TypedefDcl->getLocation());
    FileID FileIdOfEnumDcl =
      PP.getSourceManager().getFileID(EnumDcl->getLocation());
    if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
      return false;
  }
  if (TypedefDcl->isDeprecated())
    return false;

  QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
  StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);

  if (NSIntegerName.empty()) {
    // Also check for typedef enum {...} TD;
    if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
      if (EnumTy->getDecl() == EnumDcl) {
        bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
        if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
          return false;
        edit::Commit commit(*Editor);
        rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
        Editor->commit(commit);
        return true;
      }
    }
    return false;
  }

  // We may still use NS_OPTIONS based on what we find in the enumertor list.
  bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
  if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
    return false;
  edit::Commit commit(*Editor);
  bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
                                 commit, NSIntegerName, NSOptions);
  Editor->commit(commit);
  return Res;
}

static void ReplaceWithInstancetype(ASTContext &Ctx,
                                    const ObjCMigrateASTConsumer &ASTC,
                                    ObjCMethodDecl *OM) {
  if (OM->getReturnType() == Ctx.getObjCInstanceType())
    return; // already has instancetype.

  SourceRange R;
  std::string ClassString;
  if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
    TypeLoc TL = TSInfo->getTypeLoc();
    R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
    ClassString = "instancetype";
  }
  else {
    R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
    ClassString = OM->isInstanceMethod() ? '-' : '+';
    ClassString += " (instancetype)";
  }
  edit::Commit commit(*ASTC.Editor);
  commit.replace(R, ClassString);
  ASTC.Editor->commit(commit);
}

static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
                                    ObjCMethodDecl *OM) {
  ObjCInterfaceDecl *IDecl = OM->getClassInterface();
  SourceRange R;
  std::string ClassString;
  if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
    TypeLoc TL = TSInfo->getTypeLoc();
    R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
      ClassString  = IDecl->getName();
      ClassString += "*";
    }
  }
  else {
    R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
    ClassString = "+ (";
    ClassString += IDecl->getName(); ClassString += "*)";
  }
  edit::Commit commit(*ASTC.Editor);
  commit.replace(R, ClassString);
  ASTC.Editor->commit(commit);
}

void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
                                                       ObjCContainerDecl *CDecl,
                                                       ObjCMethodDecl *OM) {
  ObjCInstanceTypeFamily OIT_Family =
    Selector::getInstTypeMethodFamily(OM->getSelector());

  std::string ClassName;
  switch (OIT_Family) {
    case OIT_None:
      migrateFactoryMethod(Ctx, CDecl, OM);
      return;
    case OIT_Array:
      ClassName = "NSArray";
      break;
    case OIT_Dictionary:
      ClassName = "NSDictionary";
      break;
    case OIT_Singleton:
      migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
      return;
    case OIT_Init:
      if (OM->getReturnType()->isObjCIdType())
        ReplaceWithInstancetype(Ctx, *this, OM);
      return;
    case OIT_ReturnsSelf:
      migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
      return;
  }
  if (!OM->getReturnType()->isObjCIdType())
    return;

  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
  if (!IDecl) {
    if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
      IDecl = CatDecl->getClassInterface();
    else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
      IDecl = ImpDecl->getClassInterface();
  }
  if (!IDecl ||
      !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
    migrateFactoryMethod(Ctx, CDecl, OM);
    return;
  }
  ReplaceWithInstancetype(Ctx, *this, OM);
}

static bool TypeIsInnerPointer(QualType T) {
  if (!T->isAnyPointerType())
    return false;
  if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
      T->isBlockPointerType() || T->isFunctionPointerType() ||
      ento::coreFoundation::isCFObjectRef(T))
    return false;
  // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
  // is not an innter pointer type.
  QualType OrigT = T;
  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr()))
    T = TD->getDecl()->getUnderlyingType();
  if (OrigT == T || !T->isPointerType())
    return true;
  const PointerType* PT = T->getAs<PointerType>();
  QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
  if (UPointeeT->isRecordType()) {
    const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
    if (!RecordTy->getDecl()->isCompleteDefinition())
      return false;
  }
  return true;
}

/// Check whether the two versions match.
static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
  return (X == Y);
}

/// AvailabilityAttrsMatch - This routine checks that if comparing two
/// availability attributes, all their components match. It returns
/// true, if not dealing with availability or when all components of
/// availability attributes match. This routine is only called when
/// the attributes are of the same kind.
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
  const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
  if (!AA1)
    return true;
  const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);

  VersionTuple Introduced1 = AA1->getIntroduced();
  VersionTuple Deprecated1 = AA1->getDeprecated();
  VersionTuple Obsoleted1 = AA1->getObsoleted();
  bool IsUnavailable1 = AA1->getUnavailable();
  VersionTuple Introduced2 = AA2->getIntroduced();
  VersionTuple Deprecated2 = AA2->getDeprecated();
  VersionTuple Obsoleted2 = AA2->getObsoleted();
  bool IsUnavailable2 = AA2->getUnavailable();
  return (versionsMatch(Introduced1, Introduced2) &&
          versionsMatch(Deprecated1, Deprecated2) &&
          versionsMatch(Obsoleted1, Obsoleted2) &&
          IsUnavailable1 == IsUnavailable2);
}

static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
                                   bool &AvailabilityArgsMatch) {
  // This list is very small, so this need not be optimized.
  for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
    bool match = false;
    for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
      // Matching attribute kind only. Except for Availability attributes,
      // we are not getting into details of the attributes. For all practical purposes
      // this is sufficient.
      if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
        if (AvailabilityArgsMatch)
          AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
        match = true;
        break;
      }
    }
    if (!match)
      return false;
  }
  return true;
}

/// AttributesMatch - This routine checks list of attributes for two
/// decls. It returns false, if there is a mismatch in kind of
/// attributes seen in the decls. It returns true if the two decls
/// have list of same kind of attributes. Furthermore, when there
/// are availability attributes in the two decls, it sets the
/// AvailabilityArgsMatch to false if availability attributes have
/// different versions, etc.
static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
                            bool &AvailabilityArgsMatch) {
  if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
    AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
    return true;
  }
  AvailabilityArgsMatch = true;
  const AttrVec &Attrs1 = Decl1->getAttrs();
  const AttrVec &Attrs2 = Decl2->getAttrs();
  bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
  if (match && (Attrs2.size() > Attrs1.size()))
    return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
  return match;
}

static bool IsValidIdentifier(ASTContext &Ctx,
                              const char *Name) {
  if (!isIdentifierHead(Name[0]))
    return false;
  std::string NameString = Name;
  NameString[0] = toLowercase(NameString[0]);
  IdentifierInfo *II = &Ctx.Idents.get(NameString);
  return II->getTokenID() ==  tok::identifier;
}

bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
                             ObjCContainerDecl *D,
                             ObjCMethodDecl *Method) {
  if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
      Method->param_size() != 0)
    return false;
  // Is this method candidate to be a getter?
  QualType GRT = Method->getReturnType();
  if (GRT->isVoidType())
    return false;

  Selector GetterSelector = Method->getSelector();
  ObjCInstanceTypeFamily OIT_Family =
    Selector::getInstTypeMethodFamily(GetterSelector);

  if (OIT_Family != OIT_None)
    return false;

  IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
  Selector SetterSelector =
  SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
                                         PP.getSelectorTable(),
                                         getterName);
  ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
  unsigned LengthOfPrefix = 0;
  if (!SetterMethod) {
    // try a different naming convention for getter: isXxxxx
    StringRef getterNameString = getterName->getName();
    bool IsPrefix = getterNameString.startswith("is");
    // Note that we don't want to change an isXXX method of retainable object
    // type to property (readonly or otherwise).
    if (IsPrefix && GRT->isObjCRetainableType())
      return false;
    if (IsPrefix || getterNameString.startswith("get")) {
      LengthOfPrefix = (IsPrefix ? 2 : 3);
      const char *CGetterName = getterNameString.data() + LengthOfPrefix;
      // Make sure that first character after "is" or "get" prefix can
      // start an identifier.
      if (!IsValidIdentifier(Ctx, CGetterName))
        return false;
      if (CGetterName[0] && isUppercase(CGetterName[0])) {
        getterName = &Ctx.Idents.get(CGetterName);
        SetterSelector =
        SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
                                               PP.getSelectorTable(),
                                               getterName);
        SetterMethod = D->getInstanceMethod(SetterSelector);
      }
    }
  }

  if (SetterMethod) {
    if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
      return false;
    bool AvailabilityArgsMatch;
    if (SetterMethod->isDeprecated() ||
        !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
      return false;

    // Is this a valid setter, matching the target getter?
    QualType SRT = SetterMethod->getReturnType();
    if (!SRT->isVoidType())
      return false;
    const ParmVarDecl *argDecl = *SetterMethod->param_begin();
    QualType ArgType = argDecl->getType();
    if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
      return false;
    edit::Commit commit(*Editor);
    rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
                          LengthOfPrefix,
                          (ASTMigrateActions &
                           FrontendOptions::ObjCMT_AtomicProperty) != 0,
                          (ASTMigrateActions &
                           FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
                          AvailabilityArgsMatch);
    Editor->commit(commit);
    return true;
  }
  else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
    // Try a non-void method with no argument (and no setter or property of same name
    // as a 'readonly' property.
    edit::Commit commit(*Editor);
    rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
                          LengthOfPrefix,
                          (ASTMigrateActions &
                           FrontendOptions::ObjCMT_AtomicProperty) != 0,
                          (ASTMigrateActions &
                           FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
                          /*AvailabilityArgsMatch*/false);
    Editor->commit(commit);
    return true;
  }
  return false;
}

void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
                                                          ObjCMethodDecl *OM) {
  if (OM->isImplicit() ||
      !OM->isInstanceMethod() ||
      OM->hasAttr<ObjCReturnsInnerPointerAttr>())
    return;

  QualType RT = OM->getReturnType();
  if (!TypeIsInnerPointer(RT) ||
      !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
    return;

  edit::Commit commit(*Editor);
  commit.insertBefore(OM->getEndLoc(), " NS_RETURNS_INNER_POINTER");
  Editor->commit(commit);
}

void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
                                                                  ObjCPropertyDecl *P) {
  QualType T = P->getType();

  if (!TypeIsInnerPointer(T) ||
      !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
    return;
  edit::Commit commit(*Editor);
  commit.insertBefore(P->getEndLoc(), " NS_RETURNS_INNER_POINTER ");
  Editor->commit(commit);
}

void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
                                                 ObjCContainerDecl *CDecl) {
  if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
    return;

  // migrate methods which can have instancetype as their result type.
  for (auto *Method : CDecl->methods()) {
    if (Method->isDeprecated())
      continue;
    migrateMethodInstanceType(Ctx, CDecl, Method);
  }
}

void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
                                                  ObjCContainerDecl *CDecl,
                                                  ObjCMethodDecl *OM,
                                                  ObjCInstanceTypeFamily OIT_Family) {
  if (OM->isInstanceMethod() ||
      OM->getReturnType() == Ctx.getObjCInstanceType() ||
      !OM->getReturnType()->isObjCIdType())
    return;

  // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
  // NSYYYNamE with matching names be at least 3 characters long.
  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
  if (!IDecl) {
    if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
      IDecl = CatDecl->getClassInterface();
    else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
      IDecl = ImpDecl->getClassInterface();
  }
  if (!IDecl)
    return;

  std::string StringClassName = IDecl->getName();
  StringRef LoweredClassName(StringClassName);
  std::string StringLoweredClassName = LoweredClassName.lower();
  LoweredClassName = StringLoweredClassName;

  IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
  // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
  if (!MethodIdName)
    return;

  std::string MethodName = MethodIdName->getName();
  if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
    StringRef STRefMethodName(MethodName);
    size_t len = 0;
    if (STRefMethodName.startswith("standard"))
      len = strlen("standard");
    else if (STRefMethodName.startswith("shared"))
      len = strlen("shared");
    else if (STRefMethodName.startswith("default"))
      len = strlen("default");
    else
      return;
    MethodName = STRefMethodName.substr(len);
  }
  std::string MethodNameSubStr = MethodName.substr(0, 3);
  StringRef MethodNamePrefix(MethodNameSubStr);
  std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
  MethodNamePrefix = StringLoweredMethodNamePrefix;
  size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
  if (Ix == StringRef::npos)
    return;
  std::string ClassNamePostfix = LoweredClassName.substr(Ix);
  StringRef LoweredMethodName(MethodName);
  std::string StringLoweredMethodName = LoweredMethodName.lower();
  LoweredMethodName = StringLoweredMethodName;
  if (!LoweredMethodName.startswith(ClassNamePostfix))
    return;
  if (OIT_Family == OIT_ReturnsSelf)
    ReplaceWithClasstype(*this, OM);
  else
    ReplaceWithInstancetype(Ctx, *this, OM);
}

static bool IsVoidStarType(QualType Ty) {
  if (!Ty->isPointerType())
    return false;

  while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
    Ty = TD->getDecl()->getUnderlyingType();

  // Is the type void*?
  const PointerType* PT = Ty->getAs<PointerType>();
  if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
    return true;
  return IsVoidStarType(PT->getPointeeType());
}

/// AuditedType - This routine audits the type AT and returns false if it is one of known
/// CF object types or of the "void *" variety. It returns true if we don't care about the type
/// such as a non-pointer or pointers which have no ownership issues (such as "int *").
static bool AuditedType (QualType AT) {
  if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
    return true;
  // FIXME. There isn't much we can say about CF pointer type; or is there?
  if (ento::coreFoundation::isCFObjectRef(AT) ||
      IsVoidStarType(AT) ||
      // If an ObjC object is type, assuming that it is not a CF function and
      // that it is an un-audited function.
      AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
    return false;
  // All other pointers are assumed audited as harmless.
  return true;
}

void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
  if (CFFunctionIBCandidates.empty())
    return;
  if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {
    CFFunctionIBCandidates.clear();
    FileId = FileID();
    return;
  }
  // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
  const Decl *FirstFD = CFFunctionIBCandidates[0];
  const Decl *LastFD  =
    CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
  const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
  edit::Commit commit(*Editor);
  commit.insertBefore(FirstFD->getBeginLoc(), PragmaString);
  PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
  SourceLocation EndLoc = LastFD->getEndLoc();
  // get location just past end of function location.
  EndLoc = PP.getLocForEndOfToken(EndLoc);
  if (isa<FunctionDecl>(LastFD)) {
    // For Methods, EndLoc points to the ending semcolon. So,
    // not of these extra work is needed.
    Token Tok;
    // get locaiton of token that comes after end of function.
    bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
    if (!Failed)
      EndLoc = Tok.getLocation();
  }
  commit.insertAfterToken(EndLoc, PragmaString);
  Editor->commit(commit);
  FileId = FileID();
  CFFunctionIBCandidates.clear();
}

void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
  if (Decl->isDeprecated())
    return;

  if (Decl->hasAttr<CFAuditedTransferAttr>()) {
    assert(CFFunctionIBCandidates.empty() &&
           "Cannot have audited functions/methods inside user "
           "provided CF_IMPLICIT_BRIDGING_ENABLE");
    return;
  }

  // Finction must be annotated first.
  if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
    CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
    if (AuditKind == CF_BRIDGING_ENABLE) {
      CFFunctionIBCandidates.push_back(Decl);
      if (FileId.isInvalid())
        FileId = PP.getSourceManager().getFileID(Decl->getLocation());
    }
    else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
      if (!CFFunctionIBCandidates.empty()) {
        CFFunctionIBCandidates.push_back(Decl);
        if (FileId.isInvalid())
          FileId = PP.getSourceManager().getFileID(Decl->getLocation());
      }
    }
    else
      AnnotateImplicitBridging(Ctx);
  }
  else {
    migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
    AnnotateImplicitBridging(Ctx);
  }
}

void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
                                              const RetainSummary *RS,
                                              const FunctionDecl *FuncDecl,
                                              bool ResultAnnotated) {
  // Annotate function.
  if (!ResultAnnotated) {
    RetEffect Ret = RS->getRetEffect();
    const char *AnnotationString = nullptr;
    if (Ret.getObjKind() == ObjKind::CF) {
      if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
        AnnotationString = " CF_RETURNS_RETAINED";
      else if (Ret.notOwned() &&
               NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
        AnnotationString = " CF_RETURNS_NOT_RETAINED";
    }
    else if (Ret.getObjKind() == ObjKind::ObjC) {
      if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
        AnnotationString = " NS_RETURNS_RETAINED";
    }

    if (AnnotationString) {
      edit::Commit commit(*Editor);
      commit.insertAfterToken(FuncDecl->getEndLoc(), AnnotationString);
      Editor->commit(commit);
    }
  }
  unsigned i = 0;
  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
       pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
    const ParmVarDecl *pd = *pi;
    ArgEffect AE = RS->getArg(i);
    if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
        !pd->hasAttr<CFConsumedAttr>() &&
        NSAPIObj->isMacroDefined("CF_CONSUMED")) {
      edit::Commit commit(*Editor);
      commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
      Editor->commit(commit);
    } else if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::ObjC &&
               !pd->hasAttr<NSConsumedAttr>() &&
               NSAPIObj->isMacroDefined("NS_CONSUMED")) {
      edit::Commit commit(*Editor);
      commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
      Editor->commit(commit);
    }
  }
}

ObjCMigrateASTConsumer::CF_BRIDGING_KIND
  ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
                                                  ASTContext &Ctx,
                                                  const FunctionDecl *FuncDecl) {
  if (FuncDecl->hasBody())
    return CF_BRIDGING_NONE;

  const RetainSummary *RS =
      getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
  bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
                                FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
                                FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
                                FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
                                FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());

  // Trivial case of when function is annotated and has no argument.
  if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
    return CF_BRIDGING_NONE;

  bool ReturnCFAudited = false;
  if (!FuncIsReturnAnnotated) {
    RetEffect Ret = RS->getRetEffect();
    if (Ret.getObjKind() == ObjKind::CF &&
        (Ret.isOwned() || Ret.notOwned()))
      ReturnCFAudited = true;
    else if (!AuditedType(FuncDecl->getReturnType()))
      return CF_BRIDGING_NONE;
  }

  // At this point result type is audited for potential inclusion.
  unsigned i = 0;
  bool ArgCFAudited = false;
  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
       pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
    const ParmVarDecl *pd = *pi;
    ArgEffect AE = RS->getArg(i);
    if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
         AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
      if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
        ArgCFAudited = true;
      else if (AE.getKind() == IncRef)
        ArgCFAudited = true;
    } else {
      QualType AT = pd->getType();
      if (!AuditedType(AT)) {
        AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
        return CF_BRIDGING_NONE;
      }
    }
  }
  if (ReturnCFAudited || ArgCFAudited)
    return CF_BRIDGING_ENABLE;

  return CF_BRIDGING_MAY_INCLUDE;
}

void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
                                                 ObjCContainerDecl *CDecl) {
  if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
    return;

  // migrate methods which can have instancetype as their result type.
  for (const auto *Method : CDecl->methods())
    migrateCFAnnotation(Ctx, Method);
}

void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
                                              const RetainSummary *RS,
                                              const ObjCMethodDecl *MethodDecl,
                                              bool ResultAnnotated) {
  // Annotate function.
  if (!ResultAnnotated) {
    RetEffect Ret = RS->getRetEffect();
    const char *AnnotationString = nullptr;
    if (Ret.getObjKind() == ObjKind::CF) {
      if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
        AnnotationString = " CF_RETURNS_RETAINED";
      else if (Ret.notOwned() &&
               NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
        AnnotationString = " CF_RETURNS_NOT_RETAINED";
    }
    else if (Ret.getObjKind() == ObjKind::ObjC) {
      ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
      switch (OMF) {
        case clang::OMF_alloc:
        case clang::OMF_new:
        case clang::OMF_copy:
        case clang::OMF_init:
        case clang::OMF_mutableCopy:
          break;

        default:
          if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
            AnnotationString = " NS_RETURNS_RETAINED";
          break;
      }
    }

    if (AnnotationString) {
      edit::Commit commit(*Editor);
      commit.insertBefore(MethodDecl->getEndLoc(), AnnotationString);
      Editor->commit(commit);
    }
  }
  unsigned i = 0;
  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
       pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
    const ParmVarDecl *pd = *pi;
    ArgEffect AE = RS->getArg(i);
    if (AE.getKind() == DecRef
        && AE.getObjKind() == ObjKind::CF
        && !pd->hasAttr<CFConsumedAttr>() &&
        NSAPIObj->isMacroDefined("CF_CONSUMED")) {
      edit::Commit commit(*Editor);
      commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
      Editor->commit(commit);
    }
  }
}

void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
                                            ASTContext &Ctx,
                                            const ObjCMethodDecl *MethodDecl) {
  if (MethodDecl->hasBody() || MethodDecl->isImplicit())
    return;

  const RetainSummary *RS =
      getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));

  bool MethodIsReturnAnnotated =
      (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
       MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
       MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
       MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
       MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());

  if (RS->getReceiverEffect().getKind() == DecRef &&
      !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
      MethodDecl->getMethodFamily() != OMF_init &&
      MethodDecl->getMethodFamily() != OMF_release &&
      NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
    edit::Commit commit(*Editor);
    commit.insertBefore(MethodDecl->getEndLoc(), " NS_CONSUMES_SELF");
    Editor->commit(commit);
  }

  // Trivial case of when function is annotated and has no argument.
  if (MethodIsReturnAnnotated &&
      (MethodDecl->param_begin() == MethodDecl->param_end()))
    return;

  if (!MethodIsReturnAnnotated) {
    RetEffect Ret = RS->getRetEffect();
    if ((Ret.getObjKind() == ObjKind::CF ||
         Ret.getObjKind() == ObjKind::ObjC) &&
        (Ret.isOwned() || Ret.notOwned())) {
      AddCFAnnotations(Ctx, RS, MethodDecl, false);
      return;
    } else if (!AuditedType(MethodDecl->getReturnType()))
      return;
  }

  // At this point result type is either annotated or audited.
  unsigned i = 0;
  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
       pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
    const ParmVarDecl *pd = *pi;
    ArgEffect AE = RS->getArg(i);
    if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
        AE.getKind() == IncRef || !AuditedType(pd->getType())) {
      AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
      return;
    }
  }
}

namespace {
class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
public:
  bool shouldVisitTemplateInstantiations() const { return false; }
  bool shouldWalkTypesOfTypeLocs() const { return false; }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
      if (E->getMethodFamily() == OMF_init)
        return false;
    }
    return true;
  }
};
} // end anonymous namespace

static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
  return !SuperInitChecker().TraverseStmt(MD->getBody());
}

void ObjCMigrateASTConsumer::inferDesignatedInitializers(
    ASTContext &Ctx,
    const ObjCImplementationDecl *ImplD) {

  const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
  if (!IFace || IFace->hasDesignatedInitializers())
    return;
  if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
    return;

  for (const auto *MD : ImplD->instance_methods()) {
    if (MD->isDeprecated() ||
        MD->getMethodFamily() != OMF_init ||
        MD->isDesignatedInitializerForTheInterface())
      continue;
    const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
                                                    /*isInstance=*/true);
    if (!IFaceM)
      continue;
    if (hasSuperInitCall(MD)) {
      edit::Commit commit(*Editor);
      commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");
      Editor->commit(commit);
    }
  }
}

bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
                                              SourceLocation  Loc) {
  if (FoundationIncluded)
    return true;
  if (Loc.isInvalid())
    return false;
  auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");
  if (PP.getMacroDefinitionAtLoc(nsEnumId, Loc)) {
    FoundationIncluded = true;
    return true;
  }
  edit::Commit commit(*Editor);
  if (Ctx.getLangOpts().Modules)
    commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
  else
    commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
  Editor->commit(commit);
  FoundationIncluded = true;
  return true;
}

namespace {

class RewritesReceiver : public edit::EditsReceiver {
  Rewriter &Rewrite;

public:
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }

  void insert(SourceLocation loc, StringRef text) override {
    Rewrite.InsertText(loc, text);
  }
  void replace(CharSourceRange range, StringRef text) override {
    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
  }
};

class JSONEditWriter : public edit::EditsReceiver {
  SourceManager &SourceMgr;
  llvm::raw_ostream &OS;

public:
  JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
    : SourceMgr(SM), OS(OS) {
    OS << "[\n";
  }
  ~JSONEditWriter() override { OS << "]\n"; }

private:
  struct EntryWriter {
    SourceManager &SourceMgr;
    llvm::raw_ostream &OS;

    EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
      : SourceMgr(SM), OS(OS) {
      OS << " {\n";
    }
    ~EntryWriter() {
      OS << " },\n";
    }

    void writeLoc(SourceLocation Loc) {
      FileID FID;
      unsigned Offset;
      std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
      assert(FID.isValid());
      SmallString<200> Path =
          StringRef(SourceMgr.getFileEntryForID(FID)->getName());
      llvm::sys::fs::make_absolute(Path);
      OS << "  \"file\": \"";
      OS.write_escaped(Path.str()) << "\",\n";
      OS << "  \"offset\": " << Offset << ",\n";
    }

    void writeRemove(CharSourceRange Range) {
      assert(Range.isCharRange());
      std::pair<FileID, unsigned> Begin =
          SourceMgr.getDecomposedLoc(Range.getBegin());
      std::pair<FileID, unsigned> End =
          SourceMgr.getDecomposedLoc(Range.getEnd());
      assert(Begin.first == End.first);
      assert(Begin.second <= End.second);
      unsigned Length = End.second - Begin.second;

      OS << "  \"remove\": " << Length << ",\n";
    }

    void writeText(StringRef Text) {
      OS << "  \"text\": \"";
      OS.write_escaped(Text) << "\",\n";
    }
  };

  void insert(SourceLocation Loc, StringRef Text) override {
    EntryWriter Writer(SourceMgr, OS);
    Writer.writeLoc(Loc);
    Writer.writeText(Text);
  }

  void replace(CharSourceRange Range, StringRef Text) override {
    EntryWriter Writer(SourceMgr, OS);
    Writer.writeLoc(Range.getBegin());
    Writer.writeRemove(Range);
    Writer.writeText(Text);
  }

  void remove(CharSourceRange Range) override {
    EntryWriter Writer(SourceMgr, OS);
    Writer.writeLoc(Range.getBegin());
    Writer.writeRemove(Range);
  }
};

} // end anonymous namespace

void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {

  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
  if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
    for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
         D != DEnd; ++D) {
      FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
      if (FID.isValid())
        if (FileId.isValid() && FileId != FID) {
          if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
            AnnotateImplicitBridging(Ctx);
        }

      if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
        if (canModify(CDecl))
          migrateObjCContainerDecl(Ctx, CDecl);
      if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
        if (canModify(CatDecl))
          migrateObjCContainerDecl(Ctx, CatDecl);
      }
      else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
        ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
        if (canModify(PDecl))
          migrateObjCContainerDecl(Ctx, PDecl);
      }
      else if (const ObjCImplementationDecl *ImpDecl =
               dyn_cast<ObjCImplementationDecl>(*D)) {
        if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
            canModify(ImpDecl))
          migrateProtocolConformance(Ctx, ImpDecl);
      }
      else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
        if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
          continue;
        if (!canModify(ED))
          continue;
        DeclContext::decl_iterator N = D;
        if (++N != DEnd) {
          const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
          if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
            D++;
        }
        else
          migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
      }
      else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
        if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
          continue;
        if (!canModify(TD))
          continue;
        DeclContext::decl_iterator N = D;
        if (++N == DEnd)
          continue;
        if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
          if (canModify(ED)) {
            if (++N != DEnd)
              if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
                // prefer typedef-follows-enum to enum-follows-typedef pattern.
                if (migrateNSEnumDecl(Ctx, ED, TDF)) {
                  ++D; ++D;
                  CacheObjCNSIntegerTypedefed(TD);
                  continue;
                }
              }
            if (migrateNSEnumDecl(Ctx, ED, TD)) {
              ++D;
              continue;
            }
          }
        }
        CacheObjCNSIntegerTypedefed(TD);
      }
      else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
        if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
            canModify(FD))
          migrateCFAnnotation(Ctx, FD);
      }

      if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
        bool CanModify = canModify(CDecl);
        // migrate methods which can have instancetype as their result type.
        if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
            CanModify)
          migrateAllMethodInstaceType(Ctx, CDecl);
        // annotate methods with CF annotations.
        if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
            CanModify)
          migrateARCSafeAnnotation(Ctx, CDecl);
      }

      if (const ObjCImplementationDecl *
            ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
        if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
            canModify(ImplD))
          inferDesignatedInitializers(Ctx, ImplD);
      }
    }
    if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
      AnnotateImplicitBridging(Ctx);
  }

 if (IsOutputFile) {
   std::error_code EC;
   llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::OF_None);
   if (EC) {
      DiagnosticsEngine &Diags = Ctx.getDiagnostics();
      Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
          << EC.message();
      return;
    }

   JSONEditWriter Writer(Ctx.getSourceManager(), OS);
   Editor->applyRewrites(Writer);
   return;
 }

  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
  RewritesReceiver Rec(rewriter);
  Editor->applyRewrites(Rec);

  for (Rewriter::buffer_iterator
        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
    FileID FID = I->first;
    RewriteBuffer &buf = I->second;
    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
    assert(file);
    SmallString<512> newText;
    llvm::raw_svector_ostream vecOS(newText);
    buf.write(vecOS);
    std::unique_ptr<llvm::MemoryBuffer> memBuf(
        llvm::MemoryBuffer::getMemBufferCopy(
            StringRef(newText.data(), newText.size()), file->getName()));
    SmallString<64> filePath(file->getName());
    FileMgr.FixupRelativePath(filePath);
    Remapper.remap(filePath.str(), std::move(memBuf));
  }

  if (IsOutputFile) {
    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
  } else {
    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
  }
}

bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
  CI.getDiagnostics().setIgnoreAllWarnings(true);
  return true;
}

static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
  using namespace llvm::sys::fs;
  using namespace llvm::sys::path;

  std::vector<std::string> Filenames;
  if (DirPath.empty() || !is_directory(DirPath))
    return Filenames;

  std::error_code EC;
  directory_iterator DI = directory_iterator(DirPath, EC);
  directory_iterator DE;
  for (; !EC && DI != DE; DI = DI.increment(EC)) {
    if (is_regular_file(DI->path()))
      Filenames.push_back(filename(DI->path()));
  }

  return Filenames;
}

std::unique_ptr<ASTConsumer>
MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  PPConditionalDirectiveRecord *
    PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
  unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
  unsigned ObjCMTOpts = ObjCMTAction;
  // These are companion flags, they do not enable transformations.
  ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
                  FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty);
  if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
    // If no specific option was given, enable literals+subscripting transforms
    // by default.
    ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
                    FrontendOptions::ObjCMT_Subscripting;
  }
  CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
  std::vector<std::string> WhiteList =
    getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath);
  return std::make_unique<ObjCMigrateASTConsumer>(
      CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
      CI.getFileManager(), PPRec, CI.getPreprocessor(),
      /*isOutputFile=*/true, WhiteList);
}

namespace {
struct EditEntry {
  const FileEntry *File;
  unsigned Offset;
  unsigned RemoveLen;
  std::string Text;

  EditEntry() : File(), Offset(), RemoveLen() {}
};
} // end anonymous namespace

namespace llvm {
template<> struct DenseMapInfo<EditEntry> {
  static inline EditEntry getEmptyKey() {
    EditEntry Entry;
    Entry.Offset = unsigned(-1);
    return Entry;
  }
  static inline EditEntry getTombstoneKey() {
    EditEntry Entry;
    Entry.Offset = unsigned(-2);
    return Entry;
  }
  static unsigned getHashValue(const EditEntry& Val) {
    llvm::FoldingSetNodeID ID;
    ID.AddPointer(Val.File);
    ID.AddInteger(Val.Offset);
    ID.AddInteger(Val.RemoveLen);
    ID.AddString(Val.Text);
    return ID.ComputeHash();
  }
  static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
    return LHS.File == RHS.File &&
        LHS.Offset == RHS.Offset &&
        LHS.RemoveLen == RHS.RemoveLen &&
        LHS.Text == RHS.Text;
  }
};
} // end namespace llvm

namespace {
class RemapFileParser {
  FileManager &FileMgr;

public:
  RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }

  bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
    using namespace llvm::yaml;

    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
        llvm::MemoryBuffer::getFile(File);
    if (!FileBufOrErr)
      return true;

    llvm::SourceMgr SM;
    Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
    document_iterator I = YAMLStream.begin();
    if (I == YAMLStream.end())
      return true;
    Node *Root = I->getRoot();
    if (!Root)
      return true;

    SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
    if (!SeqNode)
      return true;

    for (SequenceNode::iterator
           AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
      MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
      if (!MapNode)
        continue;
      parseEdit(MapNode, Entries);
    }

    return false;
  }

private:
  void parseEdit(llvm::yaml::MappingNode *Node,
                 SmallVectorImpl<EditEntry> &Entries) {
    using namespace llvm::yaml;
    EditEntry Entry;
    bool Ignore = false;

    for (MappingNode::iterator
           KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
      ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
      if (!KeyString)
        continue;
      SmallString<10> KeyStorage;
      StringRef Key = KeyString->getValue(KeyStorage);

      ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
      if (!ValueString)
        continue;
      SmallString<64> ValueStorage;
      StringRef Val = ValueString->getValue(ValueStorage);

      if (Key == "file") {
        auto FE = FileMgr.getFile(Val);
        if (FE)
          Entry.File = *FE;
        else
          Ignore = true;
      } else if (Key == "offset") {
        if (Val.getAsInteger(10, Entry.Offset))
          Ignore = true;
      } else if (Key == "remove") {
        if (Val.getAsInteger(10, Entry.RemoveLen))
          Ignore = true;
      } else if (Key == "text") {
        Entry.Text = Val;
      }
    }

    if (!Ignore)
      Entries.push_back(Entry);
  }
};
} // end anonymous namespace

static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
  Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
      << Err.str();
  return true;
}

static std::string applyEditsToTemp(const FileEntry *FE,
                                    ArrayRef<EditEntry> Edits,
                                    FileManager &FileMgr,
                                    DiagnosticsEngine &Diag) {
  using namespace llvm::sys;

  SourceManager SM(Diag, FileMgr);
  FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
  LangOptions LangOpts;
  edit::EditedSource Editor(SM, LangOpts);
  for (ArrayRef<EditEntry>::iterator
        I = Edits.begin(), E = Edits.end(); I != E; ++I) {
    const EditEntry &Entry = *I;
    assert(Entry.File == FE);
    SourceLocation Loc =
        SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
    CharSourceRange Range;
    if (Entry.RemoveLen != 0) {
      Range = CharSourceRange::getCharRange(Loc,
                                         Loc.getLocWithOffset(Entry.RemoveLen));
    }

    edit::Commit commit(Editor);
    if (Range.isInvalid()) {
      commit.insert(Loc, Entry.Text);
    } else if (Entry.Text.empty()) {
      commit.remove(Range);
    } else {
      commit.replace(Range, Entry.Text);
    }
    Editor.commit(commit);
  }

  Rewriter rewriter(SM, LangOpts);
  RewritesReceiver Rec(rewriter);
  Editor.applyRewrites(Rec, /*adjustRemovals=*/false);

  const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
  SmallString<512> NewText;
  llvm::raw_svector_ostream OS(NewText);
  Buf->write(OS);

  SmallString<64> TempPath;
  int FD;
  if (fs::createTemporaryFile(path::filename(FE->getName()),
                              path::extension(FE->getName()).drop_front(), FD,
                              TempPath)) {
    reportDiag("Could not create file: " + TempPath.str(), Diag);
    return std::string();
  }

  llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
  TmpOut.write(NewText.data(), NewText.size());
  TmpOut.close();

  return TempPath.str();
}

bool arcmt::getFileRemappingsFromFileList(
                        std::vector<std::pair<std::string,std::string> > &remap,
                        ArrayRef<StringRef> remapFiles,
                        DiagnosticConsumer *DiagClient) {
  bool hasErrorOccurred = false;

  FileSystemOptions FSOpts;
  FileManager FileMgr(FSOpts);
  RemapFileParser Parser(FileMgr);

  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
      new DiagnosticsEngine(DiagID, new DiagnosticOptions,
                            DiagClient, /*ShouldOwnClient=*/false));

  typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
      FileEditEntriesTy;
  FileEditEntriesTy FileEditEntries;

  llvm::DenseSet<EditEntry> EntriesSet;

  for (ArrayRef<StringRef>::iterator
         I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
    SmallVector<EditEntry, 16> Entries;
    if (Parser.parse(*I, Entries))
      continue;

    for (SmallVectorImpl<EditEntry>::iterator
           EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
      EditEntry &Entry = *EI;
      if (!Entry.File)
        continue;
      std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
        Insert = EntriesSet.insert(Entry);
      if (!Insert.second)
        continue;

      FileEditEntries[Entry.File].push_back(Entry);
    }
  }

  for (FileEditEntriesTy::iterator
         I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
    std::string TempFile = applyEditsToTemp(I->first, I->second,
                                            FileMgr, *Diags);
    if (TempFile.empty()) {
      hasErrorOccurred = true;
      continue;
    }

    remap.emplace_back(I->first->getName(), TempFile);
  }

  return hasErrorOccurred;
}
