[Reproducers] Make clang use lldb's VFS.

In r353906 we hooked up clang and lldb's reproducer infrastructure to
capture files used by clang. This patch adds the necessary logic to have
clang reuse the files from lldb's reproducer during replay.

Differential revision: https://reviews.llvm.org/D58309

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@354283 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/Host/FileSystem.h b/include/lldb/Host/FileSystem.h
index fe0386c..80621a3 100644
--- a/include/lldb/Host/FileSystem.h
+++ b/include/lldb/Host/FileSystem.h
@@ -181,6 +181,10 @@
   llvm::ErrorOr<std::string> GetExternalPath(const llvm::Twine &path);
   llvm::ErrorOr<std::string> GetExternalPath(const FileSpec &file_spec);
 
+  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> GetVirtualFileSystem() {
+    return m_fs;
+  }
+
 private:
   static llvm::Optional<FileSystem> &InstanceImpl();
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h
index 96641da..ab66e75 100644
--- a/include/lldb/Symbol/ClangASTImporter.h
+++ b/include/lldb/Symbol/ClangASTImporter.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/FileSystemOptions.h"
 
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
 #include "lldb/lldb-types.h"
 
@@ -93,7 +94,9 @@
         vbase_offsets;
   };
 
-  ClangASTImporter() : m_file_manager(clang::FileSystemOptions()) {}
+  ClangASTImporter()
+      : m_file_manager(clang::FileSystemOptions(),
+                       FileSystem::Instance().GetVirtualFileSystem()) {}
 
   clang::QualType CopyType(clang::ASTContext *dst_ctx,
                            clang::ASTContext *src_ctx, clang::QualType type);
diff --git a/lit/Reproducer/Inputs/ModuleCapture.in b/lit/Reproducer/Inputs/ModuleCapture.in
deleted file mode 100644
index 5a761c6..0000000
--- a/lit/Reproducer/Inputs/ModuleCapture.in
+++ /dev/null
@@ -1,2 +0,0 @@
-expr -- @import Cocoa
-reproducer generate
diff --git a/lit/Reproducer/Modules/Inputs/Bar.h b/lit/Reproducer/Modules/Inputs/Bar.h
new file mode 100644
index 0000000..d004baf
--- /dev/null
+++ b/lit/Reproducer/Modules/Inputs/Bar.h
@@ -0,0 +1,3 @@
+struct Bar {
+  int success;
+};
diff --git a/lit/Reproducer/Modules/Inputs/Foo.h b/lit/Reproducer/Modules/Inputs/Foo.h
new file mode 100644
index 0000000..1fe02e8
--- /dev/null
+++ b/lit/Reproducer/Modules/Inputs/Foo.h
@@ -0,0 +1 @@
+struct Foo {};
diff --git a/lit/Reproducer/Modules/Inputs/ModuleCXX.in b/lit/Reproducer/Modules/Inputs/ModuleCXX.in
new file mode 100644
index 0000000..0f5bb78
--- /dev/null
+++ b/lit/Reproducer/Modules/Inputs/ModuleCXX.in
@@ -0,0 +1,6 @@
+breakpoint set -f main.cpp -l 5
+run
+expr -l Objective-C++ -- @import Foo
+expr -l Objective-C++ -- @import Bar
+expr -- Bar()
+reproducer generate
diff --git a/lit/Reproducer/Modules/Inputs/main.cpp b/lit/Reproducer/Modules/Inputs/main.cpp
new file mode 100644
index 0000000..e6a331b
--- /dev/null
+++ b/lit/Reproducer/Modules/Inputs/main.cpp
@@ -0,0 +1,9 @@
+#include "Foo.h"
+
+void stop() {}
+
+int main(int argc, char **argv) {
+  Foo foo;
+  stop(); // break here.
+  return 0;
+}
diff --git a/lit/Reproducer/Modules/Inputs/module.modulemap b/lit/Reproducer/Modules/Inputs/module.modulemap
new file mode 100644
index 0000000..4221d0f
--- /dev/null
+++ b/lit/Reproducer/Modules/Inputs/module.modulemap
@@ -0,0 +1,7 @@
+module Foo {
+  header "Foo.h"
+}
+
+module Bar {
+  header "Bar.h"
+}
diff --git a/lit/Reproducer/Modules/TestModuleCXX.test b/lit/Reproducer/Modules/TestModuleCXX.test
new file mode 100644
index 0000000..2d4fc81
--- /dev/null
+++ b/lit/Reproducer/Modules/TestModuleCXX.test
@@ -0,0 +1,34 @@
+# Start fresh.
+# RUN: rm -rf %t.root
+# RUN: rm -rf %t.clang-cache
+# RUN: rm -rf %t.lldb-cache
+
+# Create a temporary root we can remove later.
+# RUN: mkdir -p %t.root
+# RUN: mkdir -p %t.clang-cache
+# RUN: mkdir -p %t.lldb-cache
+# RUN: cp %S/Inputs/main.cpp %t.root
+# RUN: cp %S/Inputs/Foo.h %t.root
+# RUN: cp %S/Inputs/Bar.h %t.root
+# RUN: cp %S/Inputs/module.modulemap %t.root
+
+# Compile the test case form the temporary root.
+# RUN: %clang %t.root/main.cpp -g -fmodules -fcxx-modules -fmodules-cache-path=%t.clang-cache -o %t.root/a.out
+
+# Capture the debug session.
+# RUN: %lldb -x -b -o 'settings set symbols.clang-modules-cache-path %t.lldb-cache' -s %S/Inputs/ModuleCXX.in --capture %t.repro %t.root/a.out | FileCheck %s --check-prefix CAPTURE
+# CAPTURE: (success = 0)
+
+# RUN: cat %t.repro/files.yaml | FileCheck %s --check-prefix YAML
+# YAML-DAG: Foo.h
+# YAML-DAG: Bar.h
+# YAML-DAG: module.modulemap
+
+# Remove the temporary root.
+# RUN: rm -rf %t.root
+# RUN: rm -rf %t.clang-cache
+# RUN: rm -rf %t.lldb-cache
+
+# Replay the debug session.
+# RUN: %lldb -x -b -o 'settings set symbols.clang-modules-cache-path %t.lldb-cache' -s %S/Inputs/ModuleCXX.in --replay %t.repro %t.root/a.out | FileCheck %s --check-prefix REPLAY
+# REPLAY: (success = 0)
diff --git a/lit/Reproducer/TestClangFileRepro.test b/lit/Reproducer/TestClangFileRepro.test
deleted file mode 100644
index dced57f..0000000
--- a/lit/Reproducer/TestClangFileRepro.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# REQUIRES: system-darwin
-#
-# This tests that modules files from clang end up in the reproducer.
-#
-# RUN: %lldb -x -b -s %S/Inputs/ModuleCapture.in --capture %t.repro
-# cat %t.repro/files.yaml | FileCheck %s
-#
-# CHECK: Cocoa.h
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 937d6c7..e3597d6 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -258,6 +258,10 @@
     opts.IncludeModuleFiles = true;
   }
 
+  // Make sure clang uses the same VFS as LLDB.
+  m_compiler->setVirtualFileSystem(
+      FileSystem::Instance().GetVirtualFileSystem());
+
   lldb::LanguageType frame_lang =
       expr.Language(); // defaults to lldb::eLanguageTypeUnknown
   bool overridden_target_opts = false;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index b08c454..9d5ead4 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -661,6 +661,8 @@
     opts.IncludeModuleFiles = true;
   }
 
+  // Make sure clang uses the same VFS as LLDB.
+  instance->setVirtualFileSystem(FileSystem::Instance().GetVirtualFileSystem());
   instance->setDiagnostics(diagnostics_engine.get());
   instance->setInvocation(invocation);
 
diff --git a/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
index e70e45c..a9a1b44 100644
--- a/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
+++ b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -8,6 +8,7 @@
 
 #include "ClangHighlighter.h"
 
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Utility/AnsiTerminal.h"
 #include "lldb/Utility/StreamString.h"
@@ -135,7 +136,8 @@
   using namespace clang;
 
   FileSystemOptions file_opts;
-  FileManager file_mgr(file_opts);
+  FileManager file_mgr(file_opts,
+                       FileSystem::Instance().GetVirtualFileSystem());
 
   unsigned line_number = previous_lines.count('\n') + 1U;
 
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index aafbe2e..8184f7c 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -911,7 +911,8 @@
 clang::FileManager *ClangASTContext::getFileManager() {
   if (m_file_manager_up == nullptr) {
     clang::FileSystemOptions file_system_options;
-    m_file_manager_up.reset(new clang::FileManager(file_system_options));
+    m_file_manager_up.reset(new clang::FileManager(
+        file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
   }
   return m_file_manager_up.get();
 }
diff --git a/unittests/Language/Highlighting/HighlighterTest.cpp b/unittests/Language/Highlighting/HighlighterTest.cpp
index 1faf226..8426712 100644
--- a/unittests/Language/Highlighting/HighlighterTest.cpp
+++ b/unittests/Language/Highlighting/HighlighterTest.cpp
@@ -9,6 +9,7 @@
 #include "gtest/gtest.h"
 
 #include "lldb/Core/Highlighter.h"
+#include "lldb/Host/FileSystem.h"
 
 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
@@ -27,6 +28,7 @@
 void HighlighterTest::SetUpTestCase() {
   // The HighlighterManager uses the language plugins under the hood, so we
   // have to initialize them here for our test process.
+  FileSystem::Initialize();
   CPlusPlusLanguage::Initialize();
   ObjCLanguage::Initialize();
   ObjCPlusPlusLanguage::Initialize();
@@ -36,6 +38,7 @@
   CPlusPlusLanguage::Terminate();
   ObjCLanguage::Terminate();
   ObjCPlusPlusLanguage::Terminate();
+  FileSystem::Terminate();
 }
 
 static std::string getName(lldb::LanguageType type) {