bool hasSema() const { return (bool)TheSema; }
Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
- return *TheSema;
+ return *TheSema;
}
const FileManager &getFileManager() const { return *FileMgr; }
/// @}
};
+namespace vfs {
+ class FileSystem;
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+ DiagnosticsEngine &Diags);
+
} // end namespace clang
#endif
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->Diagnostics = Diags;
- AST->FileMgr = new FileManager(FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
+ AST->FileMgr = new FileManager(FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
AST->getFileManager(),
"IR inputs not support here!");
// Configure the various subsystems.
- // FIXME: Should we retain the previous file manager?
LangOpts = &Clang->getLangOpts();
FileSystemOpts = Clang->getFileSystemOpts();
- FileMgr = new FileManager(FileSystemOpts);
+ // Re-use the existing FileManager
SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
UserFilesAreVolatile);
TheSema.reset();
TopLevelDecls.clear();
TopLevelDeclsInPreamble.clear();
PreambleDiagnostics.clear();
-
+
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
+ if (!VFS)
+ return nullptr;
+
// 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(),
AST->Diagnostics = Diags;
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
UserFilesAreVolatile);
// Create the AST unit.
OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile));
AST = OwnAST.get();
+ if (!AST)
+ return nullptr;
}
if (!ResourceFilesPath.empty()) {
= IncludeBriefCommentsInCodeCompletion;
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
// Recover resources if we crash before exiting this method.
AST->Diagnostics = Diags;
Diags = 0; // Zero out now to ease cleanup during crash recovery.
AST->FileSystemOpts = CI->getFileSystemOpts();
- AST->FileMgr = new FileManager(AST->FileSystemOpts);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(*CI, *Diags);
+ if (!VFS)
+ return nullptr;
+ AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
//===----------------------------------------------------------------------===//
#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"
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
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.
--- /dev/null
+void base_module_needs_vfs(void);
--- /dev/null
+// See vfsoverlay.yaml
+module ModuleNeedsVFS {
+ header "ModuleNeedsVFS.h"
+ export *
+}
+framework module * { }
--- /dev/null
+@import BaseModuleNeedsVFS;
+inline void module_needs_vfs(void) {
+ base_module_needs_vfs();
+}
--- /dev/null
+{
+ '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'
+ },
+ ]
+ }
+ ]
+}
--- /dev/null
+// 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
/// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can
/// not rely on the StringPool in the TU.
struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
- AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts);
+ AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);
~AllocatedCXCodeCompleteResults();
/// \brief Diagnostics produced while performing code completion.
/// \brief Language options used to adjust source locations.
LangOptions LangOpts;
- FileSystemOptions FileSystemOpts;
-
/// \brief File manager, used for diagnostics.
IntrusiveRefCntPtr<FileManager> FileMgr;
static std::atomic<unsigned> CodeCompletionResultObjects;
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
- const FileSystemOptions& FileSystemOpts)
- : CXCodeCompleteResults(),
- DiagOpts(new DiagnosticOptions),
- Diag(new DiagnosticsEngine(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- &*DiagOpts)),
- FileSystemOpts(FileSystemOpts),
- FileMgr(new FileManager(FileSystemOpts)),
- SourceMgr(new SourceManager(*Diag, *FileMgr)),
- CodeCompletionAllocator(new clang::GlobalCodeCompletionAllocator),
- Contexts(CXCompletionContext_Unknown),
- ContainerKind(CXCursor_InvalidCode),
- ContainerIsIncomplete(1)
-{
+ IntrusiveRefCntPtr<FileManager> FileMgr)
+ : CXCodeCompleteResults(),
+ DiagOpts(new DiagnosticOptions),
+ Diag(new DiagnosticsEngine(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts)),
+ FileMgr(FileMgr), SourceMgr(new SourceManager(*Diag, *FileMgr)),
+ CodeCompletionAllocator(new clang::GlobalCodeCompletionAllocator),
+ Contexts(CXCompletionContext_Unknown),
+ ContainerKind(CXCursor_InvalidCode), ContainerIsIncomplete(1) {
if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "+++ %u completion results\n",
++CodeCompletionResultObjects);
}
// Parse the resulting source file to find code-completion results.
- AllocatedCXCodeCompleteResults *Results =
- new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts());
+ AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults(
+ &AST->getFileManager());
Results->Results = 0;
Results->NumResults = 0;
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)));