aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td4
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h19
-rw-r--r--lib/Frontend/CompilerInstance.cpp39
-rw-r--r--test/Misc/Inputs/remapped-file1
-rw-r--r--test/Misc/remap-file.c5
-rw-r--r--tools/clang-cc/Options.cpp18
6 files changed, 86 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 9dbd9cfa21..50d997c986 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -33,6 +33,10 @@ def err_fe_expected_compiler_job : Error<
"unable to handle compilation, expected exactly one compiler job in '%0'">;
def err_fe_expected_clang_command : Error<
"expected a clang compiler command">;
+def err_fe_remap_missing_to_file : Error<
+ "could not remap file '%0' to the contents of file '%1'">, DefaultFatal;
+def err_fe_remap_missing_from_file : Error<
+ "could not remap from missing file '%0'">, DefaultFatal;
def err_verify_bogus_characters : Error<
"bogus characters before '{{' in expected string">;
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index f0c1d3c2c3..c43a1feb8c 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -13,6 +13,7 @@
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
@@ -41,6 +42,21 @@ public:
/// If given, a PTH cache file to use for speeding up header parsing.
std::string TokenCache;
+ /// \brief The set of file remappings, which take existing files on
+ /// the system (the first part of each pair) and gives them the
+ /// contents of other files on the system (the second part of each
+ /// pair).
+ std::vector<std::pair<std::string, std::string> > RemappedFiles;
+
+ typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ remapped_file_iterator;
+ remapped_file_iterator remapped_file_begin() const {
+ return RemappedFiles.begin();
+ }
+ remapped_file_iterator remapped_file_end() const {
+ return RemappedFiles.end();
+ }
+
public:
PreprocessorOptions() : UsePredefines(true) {}
@@ -50,6 +66,9 @@ public:
void addMacroUndef(llvm::StringRef Name) {
Macros.push_back(std::make_pair(Name, true));
}
+ void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
+ RemappedFiles.push_back(std::make_pair(From, To));
+ }
};
} // end namespace clang
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 2d58beead8..02b24b4976 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -190,6 +190,45 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
PP->setPTHManager(PTHMgr);
}
+ // Remap files in the source manager.
+ for (PreprocessorOptions::remapped_file_iterator
+ Remap = PPOpts.remapped_file_begin(),
+ RemapEnd = PPOpts.remapped_file_end();
+ Remap != RemapEnd;
+ ++Remap) {
+ // Find the file that we're mapping to.
+ const FileEntry *ToFile = FileMgr.getFile(Remap->second);
+ if (!ToFile) {
+ Diags.Report(diag::err_fe_remap_missing_to_file)
+ << Remap->first << Remap->second;
+ continue;
+ }
+
+ // Find the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getFile(Remap->first);
+ if (!FromFile) {
+ // FIXME: We could actually recover from this, by faking a
+ // FileEntry based on the "ToFile".
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << Remap->first;
+ continue;
+ }
+
+ // Load the contents of the file we're mapping to.
+ std::string ErrorStr;
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+ if (!Buffer) {
+ Diags.Report(diag::err_fe_error_opening)
+ << Remap->second << ErrorStr;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, Buffer);
+ }
+
InitializePreprocessor(*PP, PPOpts, HSOpts);
// Handle generating dependencies, if requested.
diff --git a/test/Misc/Inputs/remapped-file b/test/Misc/Inputs/remapped-file
new file mode 100644
index 0000000000..657613ed14
--- /dev/null
+++ b/test/Misc/Inputs/remapped-file
@@ -0,0 +1 @@
+int *f(float *fp) { return fp; }
diff --git a/test/Misc/remap-file.c b/test/Misc/remap-file.c
new file mode 100644
index 0000000000..e8aa3e44cc
--- /dev/null
+++ b/test/Misc/remap-file.c
@@ -0,0 +1,5 @@
+// RUN: clang-cc -remap-file="%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck %s
+
+// CHECK: remap-file.c:1:28: warning: incompatible pointer types
+
+int
diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp
index a18598ef7c..c97d4ca8c9 100644
--- a/tools/clang-cc/Options.cpp
+++ b/tools/clang-cc/Options.cpp
@@ -673,6 +673,10 @@ static llvm::cl::opt<bool>
UndefMacros("undef", llvm::cl::value_desc("macro"),
llvm::cl::desc("undef all system defines"));
+static llvm::cl::list<std::string>
+RemappedFiles("remap-file", llvm::cl::value_desc("<from>;<to>"),
+ llvm::cl::desc("replace the contents of the <from> file with the contents of the <to> file"));
+
}
//===----------------------------------------------------------------------===//
@@ -1071,6 +1075,20 @@ void clang::InitializePreprocessorOptions(PreprocessorOptions &Opts) {
for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i)
Opts.Includes.push_back(*OrderedPaths[i].second);
+
+ // Handle file remapping.
+ for (unsigned i = 0, e = RemappedFiles.size(); i != e; ++i) {
+ std::string::size_type Semi = RemappedFiles[i].find(';');
+ if (Semi == std::string::npos) {
+ // FIXME: Don't fail like this.
+ fprintf(stderr,
+ "error: -remap-file not of the form <from-file>;<to-file>\n");
+ continue;
+ }
+
+ Opts.addRemappedFile(llvm::StringRef(RemappedFiles[i].c_str(), Semi),
+ llvm::StringRef(RemappedFiles[i].c_str() + Semi + 1));
+ }
}
void clang::InitializeLangOptions(LangOptions &Options,