Extend clang_createTranslationUnitFromSourceFile() to support creating
translation units that include unsaved files.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94258 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 48296c7..2fb47cb 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -30,6 +30,7 @@
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/System/Host.h"
 #include "llvm/System/Path.h"
 using namespace clang;
@@ -103,11 +104,31 @@
 ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
                                   Diagnostic &Diags,
                                   bool OnlyLocalDecls,
-                                  bool UseBumpAllocator) {
+                                  bool UseBumpAllocator,
+                                  RemappedFile *RemappedFiles,
+                                  unsigned NumRemappedFiles) {
   llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
 
+  for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile
+      = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
+                                    RemappedFiles[I].second->getBufferSize(),
+                                             0);
+    if (!FromFile) {
+      Diags.Report(diag::err_fe_remap_missing_from_file)
+        << RemappedFiles[I].first;
+      continue;
+    }
+    
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    AST->getSourceManager().overrideFileContents(FromFile, 
+                                                 RemappedFiles[I].second);    
+  }
+  
   // Gather Info for preprocessor construction later on.
 
   LangOptions LangInfo;
@@ -289,7 +310,9 @@
                                       Diagnostic &Diags,
                                       llvm::StringRef ResourceFilesPath,
                                       bool OnlyLocalDecls,
-                                      bool UseBumpAllocator) {
+                                      bool UseBumpAllocator,
+                                      RemappedFile *RemappedFiles,
+                                      unsigned NumRemappedFiles) {
   llvm::SmallVector<const char *, 16> Args;
   Args.push_back("<clang>"); // FIXME: Remove dummy argument.
   Args.insert(Args.end(), ArgBegin, ArgEnd);
@@ -327,6 +350,11 @@
                                      (const char**) CCArgs.data()+CCArgs.size(),
                                      Diags);
 
+  // Override any files that need remapping
+  for (unsigned I = 0; I != NumRemappedFiles; ++I)
+    CI.getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+                                             RemappedFiles[I].second);
+  
   // Override the resources path.
   CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
 
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 32363ee..9aaf132 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -424,23 +424,15 @@
                                     SourceManager &SourceMgr,
                                     FileManager &FileMgr,
                                     const PreprocessorOptions &InitOpts) {
-  // Remap files in the source manager.
-  for (PreprocessorOptions::remapped_file_iterator
-         Remap = InitOpts.remapped_file_begin(),
-         RemapEnd = InitOpts.remapped_file_end();
+  // Remap files in the source manager (with buffers).
+  for (PreprocessorOptions::remapped_file_buffer_iterator
+         Remap = InitOpts.remapped_file_buffer_begin(),
+         RemapEnd = InitOpts.remapped_file_buffer_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;
-    }
-
     // Create the file entry for the file that we're mapping from.
     const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
-                                                       ToFile->getSize(),
+                                                Remap->second->getBufferSize(),
                                                        0);
     if (!FromFile) {
       Diags.Report(diag::err_fe_remap_missing_from_file)
@@ -448,16 +440,45 @@
       continue;
     }
 
+    // Override the contents of the "from" file with the contents of
+    // the "to" file.
+    SourceMgr.overrideFileContents(FromFile, Remap->second);
+  }
+
+  // Remap files in the source manager (with other files).
+  for (PreprocessorOptions::remapped_file_iterator
+       Remap = InitOpts.remapped_file_begin(),
+       RemapEnd = InitOpts.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;
+    }
+    
+    // Create the file entry for the file that we're mapping from.
+    const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+                                                       ToFile->getSize(),
+                                                       0);
+    if (!FromFile) {
+      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);
+    = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
     if (!Buffer) {
       Diags.Report(diag::err_fe_error_opening)
-        << Remap->second << ErrorStr;
+      << Remap->second << ErrorStr;
       continue;
     }
-
+    
     // Override the contents of the "from" file with the contents of
     // the "to" file.
     SourceMgr.overrideFileContents(FromFile, Buffer);