diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 3a26df3..c1273b4 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -85,6 +85,7 @@ public:
 private:
   IntrusiveRefCntPtr<LangOptions>         LangOpts;
   IntrusiveRefCntPtr<DiagnosticsEngine>   Diagnostics;
+  IntrusiveRefCntPtr<vfs::FileSystem>     VFS;
   IntrusiveRefCntPtr<FileManager>         FileMgr;
   IntrusiveRefCntPtr<SourceManager>       SourceMgr;
   std::unique_ptr<HeaderSearch>           HeaderInfo;
@@ -499,8 +500,10 @@ public:
   bool hasSema() const { return (bool)TheSema; }
   Sema &getSema() const { 
     assert(TheSema && "ASTUnit does not have a Sema object!");
-    return *TheSema; 
+    return *TheSema;
   }
+
+  vfs::FileSystem& getVirtualFileSystem() { return *VFS; }
   
   const FileManager &getFileManager() const { return *FileMgr; }
         FileManager &getFileManager()       { return *FileMgr; }
@@ -845,6 +848,7 @@ public:
                     CodeCompleteConsumer &Consumer,
                     DiagnosticsEngine &Diag, LangOptions &LangOpts,
                     SourceManager &SourceMgr, FileManager &FileMgr,
+                    vfs::FileSystem &VFS,
                     SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
               SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
 
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index f64773c..7258dbe 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -204,6 +204,14 @@ public:
   /// @}
 };
 
+namespace vfs {
+  class FileSystem;
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+                                DiagnosticsEngine &Diags);
+
 } // end namespace clang
 
 #endif
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c4f7596..bada7cd 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -692,7 +692,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->Diagnostics = Diags;
-  AST->FileMgr = new FileManager(FileSystemOpts);
+  AST->VFS = vfs::getRealFileSystem();
+  AST->FileMgr = new FileManager(FileSystemOpts, AST->VFS);
   AST->UserFilesAreVolatile = UserFilesAreVolatile;
   AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
                                      AST->getFileManager(),
@@ -1096,7 +1097,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
   // FIXME: Should we retain the previous file manager?
   LangOpts = &Clang->getLangOpts();
   FileSystemOpts = Clang->getFileSystemOpts();
-  FileMgr = new FileManager(FileSystemOpts);
+  assert(VFS && "missing VFS");
+  FileMgr = new FileManager(FileSystemOpts, VFS);
   SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
                                 UserFilesAreVolatile);
   TheSema.reset();
@@ -1114,6 +1116,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
     TopLevelDeclsInPreamble.clear();
   }
 
+  Clang->setVirtualFileSystem(VFS);
+
   // Create a file manager object to provide access to and cache the filesystem.
   Clang->setFileManager(&getFileManager());
   
@@ -1598,9 +1602,16 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
   TopLevelDecls.clear();
   TopLevelDeclsInPreamble.clear();
   PreambleDiagnostics.clear();
-  
+
+  IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+      createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
+  if (!VFS)
+    return nullptr;
+
+  Clang->setVirtualFileSystem(VFS);
+
   // Create a file manager object to provide access to and cache the filesystem.
-  Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
+  Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
   
   // Create the source manager.
   Clang->setSourceManager(new SourceManager(getDiagnostics(),
@@ -1758,7 +1769,10 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI,
   AST->Diagnostics = Diags;
   AST->Invocation = CI;
   AST->FileSystemOpts = CI->getFileSystemOpts();
-  AST->FileMgr = new FileManager(AST->FileSystemOpts);
+  AST->VFS = createVFSFromCompilerInvocation(*CI, *Diags);
+  if (!AST->VFS)
+    return nullptr;
+  AST->FileMgr = new FileManager(AST->FileSystemOpts, AST->VFS);
   AST->UserFilesAreVolatile = UserFilesAreVolatile;
   AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
                                      UserFilesAreVolatile);
@@ -1781,6 +1795,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
     // Create the AST unit.
     OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile));
     AST = OwnAST.get();
+    if (!AST)
+      return nullptr;
   }
   
   if (!ResourceFilesPath.empty()) {
@@ -1846,6 +1862,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
   AST->Ctx = 0;
   AST->PP = 0;
   AST->Reader = 0;
+
+  Clang->setVirtualFileSystem(&AST->getVirtualFileSystem());
   
   // Create a file manager object to provide access to and cache the filesystem.
   Clang->setFileManager(&AST->getFileManager());
@@ -1950,7 +1968,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
     = IncludeBriefCommentsInCodeCompletion;
   AST->Invocation = CI;
   AST->FileSystemOpts = CI->getFileSystemOpts();
-  AST->FileMgr = new FileManager(AST->FileSystemOpts);
+  AST->VFS = createVFSFromCompilerInvocation(*CI, *Diags);
+  if (AST->VFS == nullptr)
+    return nullptr;
+  AST->FileMgr = new FileManager(AST->FileSystemOpts, AST->VFS);
   AST->UserFilesAreVolatile = UserFilesAreVolatile;
   
   // Recover resources if we crash before exiting this method.
@@ -2017,7 +2038,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
   AST->Diagnostics = Diags;
   Diags = 0; // Zero out now to ease cleanup during crash recovery.
   AST->FileSystemOpts = CI->getFileSystemOpts();
-  AST->FileMgr = new FileManager(AST->FileSystemOpts);
+  AST->VFS = createVFSFromCompilerInvocation(*CI, *Diags);
+  if (AST->VFS == nullptr)
+    return nullptr;
+  AST->FileMgr = new FileManager(AST->FileSystemOpts, AST->VFS);
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->TUKind = TUKind;
@@ -2348,6 +2372,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
                            CodeCompleteConsumer &Consumer,
                            DiagnosticsEngine &Diag, LangOptions &LangOpts,
                            SourceManager &SourceMgr, FileManager &FileMgr,
+                           vfs::FileSystem &VFS,
                    SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
              SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
   if (!Invocation)
@@ -2418,6 +2443,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
 
   
   // Use the source and file managers that we were given.
+  Clang->setVirtualFileSystem(&VFS);
   Clang->setFileManager(&FileMgr);
   Clang->setSourceManager(&SourceMgr);
 
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 9c95729..5aeeab7 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -8,12 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/Version.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
 #include "clang/Driver/Util.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/LangStandard.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Lex/HeaderSearchOptions.h"
@@ -1907,4 +1907,31 @@ void BuryPointer(const void *Ptr) {
     return;
   GraveYard[Idx] = Ptr;
 }
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+                                DiagnosticsEngine &Diags) {
+  if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
+    return vfs::getRealFileSystem();
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem>
+    Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+  // earlier vfs files are on the bottom
+  for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
+    std::unique_ptr<llvm::MemoryBuffer> Buffer;
+    if (llvm::errc::success != llvm::MemoryBuffer::getFile(File, Buffer)) {
+      Diags.Report(diag::err_missing_vfs_overlay_file) << File;
+      return IntrusiveRefCntPtr<vfs::FileSystem>();
+    }
+
+    IntrusiveRefCntPtr<vfs::FileSystem> FS =
+        vfs::getVFSFromYAML(Buffer.release(), /*DiagHandler*/0);
+    if (!FS.getPtr()) {
+      Diags.Report(diag::err_invalid_vfs_overlay) << File;
+      return IntrusiveRefCntPtr<vfs::FileSystem>();
+    }
+    Overlay->pushOverlay(FS);
+  }
+  return Overlay;
 }
+} // end namespace clang
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index d2ece7e..88276d0 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -211,30 +211,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     return true;
   }
 
-  if (!CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
-    IntrusiveRefCntPtr<vfs::OverlayFileSystem>
-        Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
-    // earlier vfs files are on the bottom
-    const std::vector<std::string> &Files =
-        CI.getHeaderSearchOpts().VFSOverlayFiles;
-    for (std::vector<std::string>::const_iterator I = Files.begin(),
-                                                  E = Files.end();
-         I != E; ++I) {
-      std::unique_ptr<llvm::MemoryBuffer> Buffer;
-      if (llvm::errc::success != llvm::MemoryBuffer::getFile(*I, Buffer)) {
-        CI.getDiagnostics().Report(diag::err_missing_vfs_overlay_file) << *I;
-        goto failure;
-      }
-
-      IntrusiveRefCntPtr<vfs::FileSystem> FS =
-          vfs::getVFSFromYAML(Buffer.release(), /*DiagHandler*/ 0);
-      if (!FS.getPtr()) {
-        CI.getDiagnostics().Report(diag::err_invalid_vfs_overlay) << *I;
-        goto failure;
-      }
-      Overlay->pushOverlay(FS);
-    }
-    CI.setVirtualFileSystem(Overlay);
+  if (!CI.hasVirtualFileSystem()) {
+    if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+          createVFSFromCompilerInvocation(CI.getInvocation(),
+                                          CI.getDiagnostics()))
+      CI.setVirtualFileSystem(VFS);
+    else
+      goto failure;
   }
 
   // Set up the file and source managers, if needed.
diff --git a/test/Index/Inputs/base_module_needs_vfs.h b/test/Index/Inputs/base_module_needs_vfs.h
new file mode 100644
index 0000000..9a7a244
--- /dev/null
+++ b/test/Index/Inputs/base_module_needs_vfs.h
@@ -0,0 +1 @@
+void base_module_needs_vfs(void);
diff --git a/test/Index/Inputs/module.map b/test/Index/Inputs/module.map
new file mode 100644
index 0000000..8f24840
--- /dev/null
+++ b/test/Index/Inputs/module.map
@@ -0,0 +1,6 @@
+// See vfsoverlay.yaml
+module ModuleNeedsVFS {
+  header "ModuleNeedsVFS.h"
+  export *
+}
+framework module * { }
diff --git a/test/Index/Inputs/module_needs_vfs.h b/test/Index/Inputs/module_needs_vfs.h
new file mode 100644
index 0000000..d79cc3f
--- /dev/null
+++ b/test/Index/Inputs/module_needs_vfs.h
@@ -0,0 +1,4 @@
+@import BaseModuleNeedsVFS;
+inline void module_needs_vfs(void) {
+  base_module_needs_vfs();
+}
diff --git a/test/Index/Inputs/vfsoverlay.yaml b/test/Index/Inputs/vfsoverlay.yaml
new file mode 100644
index 0000000..95b00be
--- /dev/null
+++ b/test/Index/Inputs/vfsoverlay.yaml
@@ -0,0 +1,18 @@
+{
+  'version': 0,
+  'roots': [
+    { 'name': 'OUT_DIR', 'type': 'directory',
+      'contents': [
+        { 'name': 'module.map', 'type': 'file',
+          'external-contents': 'INPUT_DIR/module.map'
+        },
+        { 'name': 'ModuleNeedsVFS.h', 'type': 'file',
+          'external-contents': 'INPUT_DIR/module_needs_vfs.h'
+        },
+        { 'name': 'BaseModuleNeedsVFS.framework/Headers/BaseModuleNeedsVFS.h', 'type': 'file',
+          'external-contents': 'INPUT_DIR/base_module_needs_vfs.h'
+        },
+      ]
+    }
+  ]
+}
diff --git a/test/Index/index-module-with-vfs.m b/test/Index/index-module-with-vfs.m
new file mode 100644
index 0000000..f3ca60c
--- /dev/null
+++ b/test/Index/index-module-with-vfs.m
@@ -0,0 +1,26 @@
+// REQUIRES: shell
+@import ModuleNeedsVFS;
+
+void foo() {
+  module_needs_vfs();
+  base_module_needs_vfs();
+}
+
+// RUN: rm -rf %t.cache
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsoverlay.yaml > %t.yaml
+// RUN: c-index-test -index-file %s -fmodules-cache-path=%t.cache -fmodules -F %t -I %t \
+// RUN:              -ivfsoverlay %t.yaml -Xclang -fdisable-module-hash | FileCheck %s
+
+// CHECK: [importedASTFile]: {{.*}}ModuleNeedsVFS.pcm | loc: 2:1 | name: "ModuleNeedsVFS" | isImplicit: 0
+// CHECK: [indexEntityReference]: kind: function | name: module_needs_vfs
+// CHECK: [indexEntityReference]: kind: function | name: base_module_needs_vfs
+
+// RUN: c-index-test -index-tu %t.cache/ModuleNeedsVFS.pcm | FileCheck %s -check-prefix=CHECK-MOD
+
+// CHECK-MOD: [ppIncludedFile]: {{.*}}module_needs_vfs.h 
+// CHECK-MOD: [importedASTFile]: {{.*}}BaseModuleNeedsVFS.pcm
+// CHECK-MOD: [indexEntityReference]: kind: function | name: base_module_needs_vfs
+
+// RUN: c-index-test -index-tu %t.cache/BaseModuleNeedsVFS.pcm | FileCheck %s -check-prefix=CHECK-MOD2
+
+// CHECK-MOD2: [ppIncludedFile]: {{.*}}base_module_needs_vfs.h
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 5912945..4750d70 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -249,7 +249,8 @@ namespace {
 /// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can
 /// not rely on the StringPool in the TU.
 struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
-  AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts);
+  AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts,
+                                 vfs::FileSystem &VFS);
   ~AllocatedCXCodeCompleteResults();
   
   /// \brief Diagnostics produced while performing code completion.
@@ -265,6 +266,8 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
 
   FileSystemOptions FileSystemOpts;
 
+  IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+
   /// \brief File manager, used for diagnostics.
   IntrusiveRefCntPtr<FileManager> FileMgr;
 
@@ -318,14 +321,15 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
 static std::atomic<unsigned> CodeCompletionResultObjects;
   
 AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
-                                      const FileSystemOptions& FileSystemOpts)
+                                      const FileSystemOptions& FileSystemOpts,
+                                      vfs::FileSystem &VFS)
   : CXCodeCompleteResults(),
     DiagOpts(new DiagnosticOptions),
     Diag(new DiagnosticsEngine(
                    IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
                    &*DiagOpts)),
-    FileSystemOpts(FileSystemOpts),
-    FileMgr(new FileManager(FileSystemOpts)),
+    FileSystemOpts(FileSystemOpts), VFS(&VFS),
+    FileMgr(new FileManager(FileSystemOpts, &VFS)),
     SourceMgr(new SourceManager(*Diag, *FileMgr)),
     CodeCompletionAllocator(new clang::GlobalCodeCompletionAllocator),
     Contexts(CXCompletionContext_Unknown),
@@ -710,7 +714,8 @@ void clang_codeCompleteAt_Impl(void *UserData) {
 
   // Parse the resulting source file to find code-completion results.
   AllocatedCXCodeCompleteResults *Results = 
-        new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts());
+        new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts(),
+                                           AST->getVirtualFileSystem());
   Results->Results = 0;
   Results->NumResults = 0;
   
@@ -727,7 +732,7 @@ void clang_codeCompleteAt_Impl(void *UserData) {
                     IncludeBriefComments,
                     Capture,
                     *Results->Diag, Results->LangOpts, *Results->SourceMgr,
-                    *Results->FileMgr, Results->Diagnostics,
+                    *Results->FileMgr, *Results->VFS, Results->Diagnostics,
                     Results->TemporaryBuffers);
   
   // Keep a reference to the allocator used for cached global completions, so
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index 55e6e79..47ba97b 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -610,6 +610,11 @@ static void clang_indexSourceFile_Impl(void *UserData) {
   ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags,
                                   CaptureDiagnostics,
                                   /*UserFilesAreVolatile=*/true);
+  if (!Unit) {
+    ITUI->result = CXError_InvalidArguments;
+    return;
+  }
+
   std::unique_ptr<CXTUOwner> CXTU(
       new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
 
