Add clang -cc1 support for -remap-file.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90414 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 3f7d114..1b95575 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -60,6 +60,8 @@
 def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
 def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
 def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
+def err_drv_invalid_remap_file : Error<
+    "invalid option '%0' not of the form <from-file>;<to-file>">;
 
 def warn_drv_input_file_unused : Warning<
   "%0: '%1' input unused when '%2' is present">;
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 74aa11b..991de38c 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -188,6 +188,9 @@
 def code_completion_at : Separate<"-code-completion-at">,
   MetaVarName<"file:line:column">,
   HelpText<"Dump code-completion information at a location">;
+def remap_file : Separate<"-remap-file">,
+  MetaVarName<"<from>;<to>">,
+  HelpText<"Replace the contents of the <from> file with the contents of the <to> file">;
 def code_completion_at_EQ : Joined<"-code-completion-at=">,
   Alias<code_completion_at>;
 def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">,
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 3e6f9cb..4f8ab50 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -554,6 +554,11 @@
       assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
              "Unsupported option combination!");
   }
+  for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
+    Res.push_back("-remap-file");
+    Res.push_back(Opts.RemappedFiles[i].first + ";" +
+                  Opts.RemappedFiles[i].second);
+  }
 }
 
 static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
@@ -1165,7 +1170,8 @@
   }
 }
 
-static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args) {
+static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+                                  Diagnostic &Diags) {
   using namespace cc1options;
   Opts.ImplicitPCHInclude = getLastArgValue(Args, OPT_include_pch);
   Opts.ImplicitPTHInclude = getLastArgValue(Args, OPT_include_pth);
@@ -1203,6 +1209,19 @@
     } else
       Opts.Includes.push_back(it->getValue(Args));
   }
+
+  for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    std::pair<llvm::StringRef,llvm::StringRef> Split =
+      llvm::StringRef(it->getValue(Args)).split(';');
+
+    if (Split.second.empty()) {
+      Diags.Report(diag::err_drv_invalid_remap_file) << it->getAsString(Args);
+      continue;
+    }
+
+    Opts.addRemappedFile(Split.first, Split.second);
+  }
 }
 
 static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
@@ -1261,7 +1280,7 @@
                         Argv0, MainAddr);
   if (DashX != FrontendOptions::IK_AST)
     ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
-  ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args);
+  ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags);
   ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
   ParseTargetArgs(Res.getTargetOpts(), *Args);
 }