[arcmt] Introduce new '-ccc-arcmt-migrate <path>' ARC migration driver option.

This is a new mode of migration, where we avoid modifying the original files but
we emit temporary files instead.

<path> will be used to keep migration process metadata. Currently the temporary files
that are produced are put in the system's temp directory but we can put them
in the <path> if is necessary.

Also introduce new ARC migration functions in libclang whose only purpose,
currently, is to accept <path> and provide pairs of original file/transformed file
to map from the originals to the files after transformations are applied.

Finally introduce the c-arcmt-test utility that exercises the new libclang functions,
update arcmt-test, and add tests for the whole process.

rdar://9735086.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134844 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/ARCMigrate.h b/include/clang-c/ARCMigrate.h
new file mode 100644
index 0000000..00085be
--- /dev/null
+++ b/include/clang-c/ARCMigrate.h
@@ -0,0 +1,79 @@
+/*===-- clang-c/ARCMigrate.h - ARC Migration Public C Interface ---*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This header provides a public interface to a Clang library for migrating   *|
+|* objective-c source files to ARC mode.                                      *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_C_ARCMIGRATE_H
+#define CLANG_C_ARCMIGRATE_H
+
+#include "clang-c/Index.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup CARCMT libclang: C Interface to Clang ARC migration library
+ *
+ * The C Interface provides a small API that exposes facilities for translating
+ * objective-c source files of a project to Automatic Reference Counting mode.
+ *
+ * To avoid namespace pollution, data types are prefixed with "CMT" and
+ * functions are prefixed with "arcmt_".
+ *
+ * @{
+ */
+
+/**
+ * \brief A remapping of original source files and their translated files.
+ */
+typedef void *CMTRemap;
+
+/**
+ * \brief Retrieve a remapping.
+ *
+ * \param migrate_dir_path the path that clang used during the migration process.
+ *
+ * \returns the requested remapping. This remapping must be freed
+ * via a call to \c arcmt_remap_dispose(). Can return NULL if an error occurred.
+ */
+CINDEX_LINKAGE CMTRemap arcmt_getRemappings(const char *migrate_dir_path);
+
+/**
+ * \brief Determine the number of remappings.
+ */
+CINDEX_LINKAGE unsigned arcmt_remap_getNumFiles(CMTRemap);
+
+/**
+ * \brief Get the original filename.
+ */
+CINDEX_LINKAGE CXString arcmt_remap_getOriginalFile(CMTRemap, unsigned index);
+
+/**
+ * \brief Get the filename that the original file was translated into.
+ */
+CINDEX_LINKAGE
+CXString arcmt_remap_getTransformedFile(CMTRemap, unsigned index);
+
+/**
+ * \brief Dispose the remapping.
+ */
+CINDEX_LINKAGE void arcmt_remap_dispose(CMTRemap);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index 13f0778..ad5cf4a 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/include/clang/ARCMigrate/ARCMT.h
@@ -41,6 +41,23 @@
                           llvm::StringRef Filename, InputKind Kind,
                           DiagnosticClient *DiagClient);
 
+/// \brief Applies automatic modifications and produces temporary files
+/// and metadata into the \arg outputDir path.
+///
+/// \returns false if no error is produced, true otherwise.
+bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
+                               llvm::StringRef Filename, InputKind Kind,
+                               DiagnosticClient *DiagClient,
+                               llvm::StringRef outputDir);
+
+/// \brief Get the set of file remappings from the \arg outputDir path that
+/// migrateWithTemporaryFiles produced.
+///
+/// \returns false if no error is produced, true otherwise.
+bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
+                       llvm::StringRef outputDir,
+                       DiagnosticClient *DiagClient);
+
 typedef void (*TransformFn)(MigrationPass &pass);
 
 std::vector<TransformFn> getAllTransformations();
@@ -51,8 +68,8 @@
   FileRemapper Remapper;
 
 public:
-  MigrationProcess(const CompilerInvocation &CI, DiagnosticClient *diagClient)
-    : OrigCI(CI), DiagClient(diagClient) { }
+  MigrationProcess(const CompilerInvocation &CI, DiagnosticClient *diagClient,
+                   llvm::StringRef outputDir = llvm::StringRef());
 
   class RewriteListener {
   public:
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index fd85a08..4c714f5 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -24,12 +24,21 @@
   CheckAction(FrontendAction *WrappedAction);
 };
 
-class TransformationAction : public WrapperFrontendAction {
+class ModifyAction : public WrapperFrontendAction {
 protected:
   virtual bool BeginInvocation(CompilerInstance &CI);
 
 public:
-  TransformationAction(FrontendAction *WrappedAction);
+  ModifyAction(FrontendAction *WrappedAction);
+};
+
+class MigrateAction : public WrapperFrontendAction {
+  std::string MigrateDir;
+protected:
+  virtual bool BeginInvocation(CompilerInstance &CI);
+
+public:
+  MigrateAction(FrontendAction *WrappedAction, llvm::StringRef migrateDir);
 };
 
 }
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index fcd6f64..6befc8c 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -389,6 +389,10 @@
   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 import_module : Separate<"-import-module">,
   HelpText<"Import a module definition file">;
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 2cc71a9..d548276 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -118,6 +118,10 @@
   HelpText<"Apply modifications to files to conform to ARC">;
 def ccc_arrmt_check : Flag<"-ccc-arrmt-check">, Alias<ccc_arcmt_check>;
 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>;
 
 // Make sure all other -ccc- options are rejected.
 def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 3fedd6b..225a955 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -79,9 +79,12 @@
   enum {
     ARCMT_None,
     ARCMT_Check,
-    ARCMT_Modify
+    ARCMT_Modify,
+    ARCMT_Migrate
   } ARCMTAction;
 
+  std::string ARCMTMigrateDir;
+
   /// The input files and their types.
   std::vector<std::pair<InputKind, std::string> > Inputs;