//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Transforms.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 "clang/StaticAnalyzer/Checkers/ObjCRetainCount.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::objc_retain;

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 CallEffects &CE,
                        const FunctionDecl *FuncDecl, bool ResultAnnotated);
  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
                        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);

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;

  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);
  }
};

}

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(llvm::make_unique<ObjCMigrateASTConsumer>(
      MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
      CompInst->getPreprocessor(), false, None));
  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}

bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
                        /*ignoreIfFilesChanges=*/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));
  }
  
  /// \brief - 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->getLocEnd();
      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->getLocStart(), "(");
        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->getLocEnd();
      BegLoc = PP.getLocForEndOfToken(BegLoc);
      SourceLocation EndLoc = RHS->getLocStart();
      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;
  }
};
}

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->getLocStart(),
                                               EndGetterSelectorLoc),
                 PropertyString);
  if (Setter && AvailabilityArgsMatch) {
    SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
    // Get location past ';'
    EndLoc = EndLoc.getLocWithOffset(1);
    SourceLocation BeginOfSetterDclLoc = Setter->getLocStart();
    // 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->getLocStart(), EnumDcl->getLocStart());
  commit.replace(R, ClassString);
  SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
  EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
                                                 NS.getASTContext(), /*IsDecl*/true);
  if (EndOfEnumDclLoc.isValid()) {
    SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
    commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
  }
  else
    return false;
  
  SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
  EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
                                                 NS.getASTContext(), /*IsDecl*/true);
  if (EndTypedefDclLoc.isValid()) {
    SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
    commit.remove(TDRange);
  }
  else
    return false;

  EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
                                                 /*IsDecl*/true);
  if (EndOfEnumDclLoc.isValid()) {
    SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
    // 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;
  if (EnumDcl->getIntegerTypeSourceInfo()) {
    TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo();
    TypeLoc TLoc = TSourceInfo->getTypeLoc();
    EndLoc = TLoc.getLocEnd();
    const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc);
    unsigned count = 0;
    if (lbrace)
      while (lbrace[count] != '{')
        ++count;
    if (count > 0)
      EndLoc = EndLoc.getLocWithOffset(count-1);
  }
  else
    EndLoc = EnumDcl->getLocStart();
  SourceRange R(EnumDcl->getLocStart(), EndLoc);
  commit.replace(R, ClassString);
  // This is to remove spaces between '}' and typedef name.
  SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
  StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
  SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd();
  
  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->getLocEnd();
      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->getLocStart()))
          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->getLocStart()))
    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->getLocStart(), OM->getLocStart());
    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->getLocStart(), OM->getLocStart());
    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;
}

/// \brief 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 Availabilty 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->getLocEnd(), " 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->getLocEnd(), " 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->getLocStart(), PragmaString);
  PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
  SourceLocation EndLoc = LastFD->getLocEnd();
  // 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 CallEffects &CE,
                                              const FunctionDecl *FuncDecl,
                                              bool ResultAnnotated) {
  // Annotate function.
  if (!ResultAnnotated) {
    RetEffect Ret = CE.getReturnValue();
    const char *AnnotationString = nullptr;
    if (Ret.getObjKind() == RetEffect::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() == RetEffect::ObjC) {
      if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
        AnnotationString = " NS_RETURNS_RETAINED";
    }
    
    if (AnnotationString) {
      edit::Commit commit(*Editor);
      commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
      Editor->commit(commit);
    }
  }
  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  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 = AEArgs[i];
    if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
        NSAPIObj->isMacroDefined("CF_CONSUMED")) {
      edit::Commit commit(*Editor);
      commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
      Editor->commit(commit);
    }
    else if (AE == DecRefMsg && !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;
    
  CallEffects CE  = CallEffects::getEffect(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 = CE.getReturnValue();
    if (Ret.getObjKind() == RetEffect::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.
  // Now, how about argument types.
  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  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 = AEArgs[i];
    if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
      if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
        ArgCFAudited = true;
      else if (AE == IncRef)
        ArgCFAudited = true;
    }
    else {
      QualType AT = pd->getType();
      if (!AuditedType(AT)) {
        AddCFAnnotations(Ctx, CE, 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 CallEffects &CE,
                                              const ObjCMethodDecl *MethodDecl,
                                              bool ResultAnnotated) {
  // Annotate function.
  if (!ResultAnnotated) {
    RetEffect Ret = CE.getReturnValue();
    const char *AnnotationString = nullptr;
    if (Ret.getObjKind() == RetEffect::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() == RetEffect::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->getLocEnd(), AnnotationString);
      Editor->commit(commit);
    }
  }
  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  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 = AEArgs[i];
    if (AE == DecRef && !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;
  
  CallEffects CE  = CallEffects::getEffect(MethodDecl);
  bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
                                  MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
                                  MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
                                  MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
                                  MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());

  if (CE.getReceiver() == DecRefMsg &&
      !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
      MethodDecl->getMethodFamily() != OMF_init &&
      MethodDecl->getMethodFamily() != OMF_release &&
      NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
    edit::Commit commit(*Editor);
    commit.insertBefore(MethodDecl->getLocEnd(), " 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 = CE.getReturnValue();
    if ((Ret.getObjKind() == RetEffect::CF ||
         Ret.getObjKind() == RetEffect::ObjC) &&
        (Ret.isOwned() || Ret.notOwned())) {
      AddCFAnnotations(Ctx, CE, MethodDecl, false);
      return;
    } else if (!AuditedType(MethodDecl->getReturnType()))
      return;
  }
  
  // At this point result type is either annotated or audited.
  // Now, how about argument types.
  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
  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 = AEArgs[i];
    if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
        !AuditedType(pd->getType())) {
      AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
      return;
    }
  }
  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;
  }
};
} // 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->getLocEnd(), " NS_DESIGNATED_INITIALIZER");
      Editor->commit(commit);
    }
  }
}

bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
                                              SourceLocation  Loc) {
  if (FoundationIncluded)
    return true;
  if (Loc.isInvalid())
    return false;
  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);
  }
};

}

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 (++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::F_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 llvm::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() {}
};
}

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;
  }
};
}

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") {
        const FileEntry *FE = FileMgr.getFile(Val);
        if (!FE)
          Ignore = true;
        Entry.File = FE;
      } 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);
  }
};
}

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);

  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;
}
