Add new code migrator support for migrating existing Objective-C code to use
the new Objective-C NSArray/NSDictionary/NSNumber literal syntax.

This introduces a new library, libEdit, which provides a new way to support
migration of code that improves on the original ARC migrator.  We now believe
that most of its functionality can be refactored into the existing libraries,
and thus this new library may shortly disappear.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152141 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index 738a00d..86a6cbb 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/include/clang/ARCMigrate/ARCMT.h
@@ -76,6 +76,15 @@
                        StringRef outputDir,
                        DiagnosticConsumer *DiagClient);
 
+/// \brief Get the set of file remappings from a list of files with remapping
+/// info.
+///
+/// \returns false if no error is produced, true otherwise.
+bool getFileRemappingsFromFileList(
+                        std::vector<std::pair<std::string,std::string> > &remap,
+                        ArrayRef<StringRef> remapFiles,
+                        DiagnosticConsumer *DiagClient);
+
 typedef void (*TransformFn)(MigrationPass &pass);
 
 std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode,
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index 4eac4fa..e075252 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -11,6 +11,7 @@
 #define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
 
 #include "clang/Frontend/FrontendAction.h"
+#include "clang/ARCMigrate/FileRemapper.h"
 #include "llvm/ADT/OwningPtr.h"
 
 namespace clang {
@@ -32,6 +33,14 @@
   ModifyAction(FrontendAction *WrappedAction);
 };
 
+class MigrateSourceAction : public ASTFrontendAction {
+  FileRemapper Remapper;
+protected:
+  virtual bool BeginInvocation(CompilerInstance &CI);
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         StringRef InFile);
+};
+
 class MigrateAction : public WrapperFrontendAction {
   std::string MigrateDir;
   std::string PlistOut;
@@ -45,6 +54,23 @@
                 bool emitPremigrationARCErrors);
 };
 
+/// \brief Migrates to modern ObjC syntax.
+class ObjCMigrateAction : public WrapperFrontendAction {
+  std::string MigrateDir;
+  bool MigrateLiterals;
+  bool MigrateSubscripting;
+  FileRemapper Remapper;
+  CompilerInstance *CompInst;
+public:
+  ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
+                    bool migrateLiterals,
+                    bool migrateSubscripting);
+
+protected:
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile);
+  virtual bool BeginInvocation(CompilerInstance &CI);
+};
+
 }
 }
 
diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h
index a451988..fe7cfad 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -24,7 +24,7 @@
   class FileManager;
   class FileEntry;
   class DiagnosticsEngine;
-  class CompilerInvocation;
+  class PreprocessorOptions;
 
 namespace arcmt {
 
@@ -44,7 +44,10 @@
   
   bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
                     bool ignoreIfFilesChanged);
+  bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
+                    bool ignoreIfFilesChanged);
   bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
+  bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag);
 
   bool overwriteOriginal(DiagnosticsEngine &Diag,
                          StringRef outputDir = StringRef());
@@ -52,9 +55,9 @@
   void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
   void remap(StringRef filePath, StringRef newPath);
 
-  void applyMappings(CompilerInvocation &CI) const;
+  void applyMappings(PreprocessorOptions &PPOpts) const;
 
-  void transferMappingsAndClear(CompilerInvocation &CI);
+  void transferMappingsAndClear(PreprocessorOptions &PPOpts);
 
   void clear(StringRef outputDir = StringRef());
 
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 3e54b43..2b71d44 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -50,13 +50,19 @@
   /// insertion hint.
   CharSourceRange RemoveRange;
 
+  /// \brief Code in the specific range that should be inserted in the insertion
+  /// location.
+  CharSourceRange InsertFromRange;
+
   /// \brief The actual code to insert at the insertion location, as a
   /// string.
   std::string CodeToInsert;
 
+  bool BeforePreviousInsertions;
+
   /// \brief Empty code modification hint, indicating that no code
   /// modification is known.
-  FixItHint() : RemoveRange() { }
+  FixItHint() : BeforePreviousInsertions(false) { }
 
   bool isNull() const {
     return !RemoveRange.isValid();
@@ -65,11 +71,26 @@
   /// \brief Create a code modification hint that inserts the given
   /// code string at a specific location.
   static FixItHint CreateInsertion(SourceLocation InsertionLoc,
-                                   StringRef Code) {
+                                   StringRef Code,
+                                   bool BeforePreviousInsertions = false) {
     FixItHint Hint;
     Hint.RemoveRange =
       CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
     Hint.CodeToInsert = Code;
+    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
+    return Hint;
+  }
+  
+  /// \brief Create a code modification hint that inserts the given
+  /// code from \arg FromRange at a specific location.
+  static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
+                                            CharSourceRange FromRange,
+                                        bool BeforePreviousInsertions = false) {
+    FixItHint Hint;
+    Hint.RemoveRange =
+      CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
+    Hint.InsertFromRange = FromRange;
+    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
     return Hint;
   }
 
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 41ce4d9..6e317a0 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -39,6 +39,7 @@
     PreprocessJobClass,
     PrecompileJobClass,
     AnalyzeJobClass,
+    MigrateJobClass,
     CompileJobClass,
     AssembleJobClass,
     LinkJobClass,
@@ -171,6 +172,17 @@
   static bool classof(const AnalyzeJobAction *) { return true; }
 };
 
+class MigrateJobAction : public JobAction {
+  virtual void anchor();
+public:
+  MigrateJobAction(Action *Input, types::ID OutputType);
+
+  static bool classof(const Action *A) {
+    return A->getKind() == MigrateJobClass;
+  }
+  static bool classof(const MigrateJobAction *) { return true; }
+};
+
 class CompileJobAction : public JobAction {
   virtual void anchor();
 public:
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 93e63de..2fe4eba 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -433,21 +433,28 @@
   HelpText<"Rewrite ObjC into C (code rewriter example)">;
 def rewrite_macros : Flag<"-rewrite-macros">,
   HelpText<"Expand macros without full preprocessing">;
+def migrate : Flag<"-migrate">,
+  HelpText<"Migrate source code">;
 }
 
+def mt_migrate_directory : Separate<"-mt-migrate-directory">,
+  HelpText<"Directory for temporary files produced during ARC or ObjC migration">;
 def arcmt_check : Flag<"-arcmt-check">,
   HelpText<"Check for ARC migration issues that need manual handling">;
 def arcmt_modify : Flag<"-arcmt-modify">,
   HelpText<"Apply modifications to files to conform to ARC">;
 def arcmt_migrate : Flag<"-arcmt-migrate">,
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
-def arcmt_migrate_directory : Separate<"-arcmt-migrate-directory">,
-  HelpText<"Directory for temporary files produced during ARC migration">;
 def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
   HelpText<"Output path for the plist report">;
 def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
   HelpText<"Emit ARC errors even if the migrator can fix them">;
 
+def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">,
+  HelpText<"Enable migration to modern ObjC literals">;
+def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">,
+  HelpText<"Enable migration to modern ObjC subscripting">;
+
 def working_directory : JoinedOrSeparate<"-working-directory">,
   HelpText<"Resolve file paths relative to the specified directory">;
 def working_directory_EQ : Joined<"-working-directory=">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index b269ddb..51c5e02 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -118,13 +118,21 @@
 def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias<ccc_arcmt_modify>;
 def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt,
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
-def ccc_arcmt_migrate_EQ : Joined<"-ccc-arcmt-migrate=">, CCCDriverOpt,
-  Alias<ccc_arcmt_migrate>;
 def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
   HelpText<"Output path for the plist report">;
 def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
   HelpText<"Emit ARC errors even if the migrator can fix them">;
 
+def _migrate : Flag<"--migrate">, Flags<[DriverOption]>,
+  HelpText<"Run the migrator">;
+def ccc_objcmt_migrate : Separate<"-ccc-objcmt-migrate">, CCCDriverOpt,
+  HelpText<"Apply modifications and produces temporary files to migrate to "
+   "modern ObjC syntax">;
+def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">,
+  HelpText<"Enable migration to modern ObjC literals">;
+def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">,
+  HelpText<"Enable migration to modern ObjC subscripting">;
+
 // Make sure all other -ccc- options are rejected.
 def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
 
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index 8449d63..bba888c 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -82,6 +82,7 @@
 TYPE("ast",                      AST,          INVALID,         "ast",   "u")
 TYPE("plist",                    Plist,        INVALID,         "plist", "")
 TYPE("rewritten-objc",           RewrittenObjC,INVALID,         "cpp",   "")
+TYPE("remap",                    Remap,        INVALID,         "remap", "")
 TYPE("precompiled-header",       PCH,          INVALID,         "gch",   "A")
 TYPE("object",                   Object,       INVALID,         "o",     "")
 TYPE("treelang",                 Treelang,     INVALID,         0,       "u")
diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h
new file mode 100644
index 0000000..aaf6b18
--- /dev/null
+++ b/include/clang/Edit/Commit.h
@@ -0,0 +1,140 @@
+//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EDIT_COMMIT_H
+#define LLVM_CLANG_EDIT_COMMIT_H
+
+#include "clang/Edit/FileOffset.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+  class LangOptions;
+  class PreprocessingRecord;
+
+namespace edit {
+  class EditedSource;
+
+class Commit {
+public:
+  enum EditKind {
+    Act_Insert,
+    Act_InsertFromRange,
+    Act_Remove
+  };
+
+  struct Edit {
+    EditKind Kind;
+    StringRef Text;
+    SourceLocation OrigLoc;
+    FileOffset Offset;
+    FileOffset InsertFromRangeOffs;
+    unsigned Length;
+    bool BeforePrev;
+
+    SourceLocation getFileLocation(SourceManager &SM) const;
+    CharSourceRange getFileRange(SourceManager &SM) const;
+    CharSourceRange getInsertFromRange(SourceManager &SM) const;
+  };
+
+private:
+  const SourceManager &SourceMgr;
+  const LangOptions &LangOpts;
+  const PreprocessingRecord *PPRec;
+  EditedSource *Editor;
+
+  bool IsCommitable;
+  SmallVector<Edit, 8> CachedEdits;
+
+public:
+  explicit Commit(EditedSource &Editor);
+  Commit(const SourceManager &SM, const LangOptions &LangOpts,
+         const PreprocessingRecord *PPRec = 0)
+    : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0),
+      IsCommitable(true) { }
+
+  bool isCommitable() const { return IsCommitable; }
+
+  bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
+              bool beforePreviousInsertions = false);
+  bool insertAfterToken(SourceLocation loc, StringRef text,
+                        bool beforePreviousInsertions = false) {
+    return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
+  }
+  bool insertBefore(SourceLocation loc, StringRef text) {
+    return insert(loc, text, /*afterToken=*/false,
+                  /*beforePreviousInsertions=*/true);
+  }
+  bool insertFromRange(SourceLocation loc, CharSourceRange range,
+                       bool afterToken = false,
+                       bool beforePreviousInsertions = false);
+  bool insertWrap(StringRef before, CharSourceRange range, StringRef after);
+
+  bool remove(CharSourceRange range);
+
+  bool replace(CharSourceRange range, StringRef text);
+  bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange);
+  bool replaceText(SourceLocation loc, StringRef text,
+                   StringRef replacementText);
+
+  bool insertFromRange(SourceLocation loc, SourceRange TokenRange,
+                       bool afterToken = false,
+                       bool beforePreviousInsertions = false) {
+    return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
+                           afterToken, beforePreviousInsertions);
+  }
+  bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
+    return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
+  }
+  bool remove(SourceRange TokenRange) {
+    return remove(CharSourceRange::getTokenRange(TokenRange));
+  }
+  bool replace(SourceRange TokenRange, StringRef text) {
+    return replace(CharSourceRange::getTokenRange(TokenRange), text);
+  }
+  bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
+    return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
+                            CharSourceRange::getTokenRange(TokenInnerRange));
+  }
+
+  typedef SmallVector<Edit, 8>::const_iterator edit_iterator;
+  edit_iterator edit_begin() const { return CachedEdits.begin(); }
+  edit_iterator edit_end() const { return CachedEdits.end(); }
+
+private:
+  void addInsert(SourceLocation OrigLoc,
+                FileOffset Offs, StringRef text, bool beforePreviousInsertions);
+  void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
+                          FileOffset RangeOffs, unsigned RangeLen,
+                          bool beforePreviousInsertions);
+  void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len);
+
+  bool canInsert(SourceLocation loc, FileOffset &Offset);
+  bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset,
+                           SourceLocation &AfterLoc);
+  bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
+  bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len);
+  bool canReplaceText(SourceLocation loc, StringRef text,
+                      FileOffset &Offs, unsigned &Len);
+
+  void commitInsert(FileOffset offset, StringRef text,
+                    bool beforePreviousInsertions);
+  void commitRemove(FileOffset offset, unsigned length);
+
+  bool isAtStartOfMacroExpansion(SourceLocation loc,
+                                 SourceLocation *MacroBegin = 0) const;
+  bool isAtEndOfMacroExpansion(SourceLocation loc,
+                               SourceLocation *MacroEnd = 0) const;
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
new file mode 100644
index 0000000..273921c
--- /dev/null
+++ b/include/clang/Edit/EditedSource.h
@@ -0,0 +1,87 @@
+//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EDIT_EDITEDSOURCE_H
+#define LLVM_CLANG_EDIT_EDITEDSOURCE_H
+
+#include "clang/Edit/FileOffset.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <map>
+
+namespace clang {
+  class LangOptions;
+  class PreprocessingRecord;
+
+namespace edit {
+  class Commit;
+  class EditsReceiver;
+
+class EditedSource {
+  const SourceManager &SourceMgr;
+  const LangOptions &LangOpts;
+  const PreprocessingRecord *PPRec;
+
+  struct FileEdit {
+    StringRef Text;
+    unsigned RemoveLen;
+
+    FileEdit() : RemoveLen(0) {}
+  };
+
+  typedef std::map<FileOffset, FileEdit> FileEditsTy;
+  FileEditsTy FileEdits;
+
+  llvm::DenseMap<unsigned, SourceLocation> ExpansionToArgMap;
+
+  llvm::BumpPtrAllocator StrAlloc;
+
+public:
+  EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
+               const PreprocessingRecord *PPRec = 0)
+    : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec),
+      StrAlloc(/*size=*/512) { }
+
+  const SourceManager &getSourceManager() const { return SourceMgr; }
+  const LangOptions &getLangOptions() const { return LangOpts; }
+  const PreprocessingRecord *getPreprocessingRecord() const { return PPRec; }
+
+  bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
+
+  bool commit(const Commit &commit);
+  
+  void applyRewrites(EditsReceiver &receiver);
+  void clearRewrites();
+
+  StringRef copyString(StringRef str) {
+    char *buf = StrAlloc.Allocate<char>(str.size());
+    std::uninitialized_copy(str.begin(), str.end(), buf);
+    return StringRef(buf, str.size());
+  }
+  StringRef copyString(const Twine &twine);
+
+private:
+  bool commitInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
+                    bool beforePreviousInsertions);
+  bool commitInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
+                             FileOffset InsertFromRangeOffs, unsigned Len,
+                             bool beforePreviousInsertions);
+  void commitRemove(SourceLocation OrigLoc, FileOffset BeginOffs, unsigned Len);
+
+  StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs,
+                          bool &Invalid);
+  FileEditsTy::iterator getActionForOffset(FileOffset Offs);
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Edit/EditsReceiver.h b/include/clang/Edit/EditsReceiver.h
new file mode 100644
index 0000000..600ac28
--- /dev/null
+++ b/include/clang/Edit/EditsReceiver.h
@@ -0,0 +1,35 @@
+//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EDIT_EDITSRECEIVER_H
+#define LLVM_CLANG_EDIT_EDITSRECEIVER_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+  class SourceLocation;
+  class CharSourceRange;
+
+namespace edit {
+
+class EditsReceiver {
+public:
+  virtual ~EditsReceiver() { }
+
+  virtual void insert(SourceLocation loc, StringRef text) = 0;
+  virtual void replace(CharSourceRange range, StringRef text) = 0;
+  /// \brief By default it calls replace with an empty string.
+  virtual void remove(CharSourceRange range);
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Edit/FileOffset.h b/include/clang/Edit/FileOffset.h
new file mode 100644
index 0000000..675ad18
--- /dev/null
+++ b/include/clang/Edit/FileOffset.h
@@ -0,0 +1,65 @@
+//===----- FileOffset.h - Offset in a file ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EDIT_FILEOFFSET_H
+#define LLVM_CLANG_EDIT_FILEOFFSET_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+namespace edit {
+
+class FileOffset {
+  FileID FID;
+  unsigned Offs;
+public:
+  FileOffset() : Offs(0) { }
+  FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { }
+
+  bool isInvalid() const { return FID.isInvalid(); }
+
+  FileID getFID() const { return FID; }
+  unsigned getOffset() const { return Offs; }
+
+  FileOffset getWithOffset(unsigned offset) const {
+    FileOffset NewOffs = *this;
+    NewOffs.Offs += offset;
+    return NewOffs;
+  }
+
+  friend bool operator==(FileOffset LHS, FileOffset RHS) {
+    return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs;
+  }
+  friend bool operator!=(FileOffset LHS, FileOffset RHS) {
+    return !(LHS == RHS);
+  }
+  friend bool operator<(FileOffset LHS, FileOffset RHS) {
+    if (LHS.FID != RHS.FID)
+      return LHS.FID < RHS.FID;
+    return LHS.Offs < RHS.Offs;
+  }
+  friend bool operator>(FileOffset LHS, FileOffset RHS) {
+    if (LHS.FID != RHS.FID)
+      return LHS.FID > RHS.FID;
+    return LHS.Offs > RHS.Offs;
+  }
+  friend bool operator>=(FileOffset LHS, FileOffset RHS) {
+    return LHS > RHS || LHS == RHS;
+  }
+  friend bool operator<=(FileOffset LHS, FileOffset RHS) {
+    return LHS < RHS || LHS == RHS;
+  }
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Edit/Rewriters.h b/include/clang/Edit/Rewriters.h
new file mode 100644
index 0000000..aa7a5b2
--- /dev/null
+++ b/include/clang/Edit/Rewriters.h
@@ -0,0 +1,33 @@
+//===--- Rewriters.h - Rewritings     ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EDIT_REWRITERS_H
+#define LLVM_CLANG_EDIT_REWRITERS_H
+
+namespace clang {
+  class ObjCMessageExpr;
+  class NSAPI;
+
+namespace edit {
+  class Commit;
+
+bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
+                                         const NSAPI &NS, Commit &commit);
+
+bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
+                                const NSAPI &NS, Commit &commit);
+
+bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
+                                  const NSAPI &NS, Commit &commit);
+
+}
+
+}  // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index f18fdeb..0ec2f6b 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -46,6 +46,7 @@
     RewriteObjC,            ///< ObjC->C Rewriter.
     RewriteTest,            ///< Rewriter playground
     RunAnalysis,            ///< Run one or more source code analyses.
+    MigrateSource,          ///< Run migrator.
     RunPreprocessorOnly     ///< Just lex, no output.
   };
 }
@@ -118,7 +119,16 @@
     ARCMT_Migrate
   } ARCMTAction;
 
-  std::string ARCMTMigrateDir;
+  enum {
+    ObjCMT_None = 0,
+    /// \brief Enable migration to modern ObjC literals.
+    ObjCMT_Literals = 0x1,
+    /// \brief Enable migration to modern ObjC subscripting.
+    ObjCMT_Subscripting = 0x2
+  };
+  unsigned ObjCMTAction;
+
+  std::string MTMigrateDir;
   std::string ARCMTMigrateReportOut;
 
   /// The input files and their types.
@@ -177,6 +187,7 @@
     ShowVersion = 0;
     ARCMTAction = ARCMT_None;
     ARCMTMigrateEmitARCErrors = 0;
+    ObjCMTAction = ObjCMT_None;
   }
 
   /// getInputKindForExtension - Return the appropriate input kind for a file
diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h
index 0ebd62c..44f0611 100644
--- a/include/clang/Rewrite/FixItRewriter.h
+++ b/include/clang/Rewrite/FixItRewriter.h
@@ -18,6 +18,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Rewrite/Rewriter.h"
+#include "clang/Edit/EditedSource.h"
 
 namespace clang {
 
@@ -56,6 +57,8 @@
   /// \brief The diagnostics machinery.
   DiagnosticsEngine &Diags;
 
+  edit::EditedSource Editor;
+
   /// \brief The rewriter used to perform the various code
   /// modifications.
   Rewriter Rewrite;