summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clangd/FSProvider.cpp85
-rw-r--r--clang-tools-extra/clangd/FSProvider.h4
3 files changed, 87 insertions, 3 deletions
diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 2c039109d60..39467bd567e 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -23,6 +23,7 @@ add_clang_library(clangDaemon
FindSymbols.cpp
FileDistance.cpp
FS.cpp
+ FSProvider.cpp
FuzzyMatch.cpp
GlobalCompilationDatabase.cpp
Headers.cpp
diff --git a/clang-tools-extra/clangd/FSProvider.cpp b/clang-tools-extra/clangd/FSProvider.cpp
new file mode 100644
index 00000000000..d94be5bb12c
--- /dev/null
+++ b/clang-tools-extra/clangd/FSProvider.cpp
@@ -0,0 +1,85 @@
+//===--- FSProvider.cpp - VFS provider for ClangdServer -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FSProvider.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace clang {
+namespace clangd {
+
+namespace {
+/// Always opens files in the underlying filesystem as "volatile", meaning they
+/// won't be memory-mapped. This avoid locking the files on Windows.
+class VolatileFileSystem : public llvm::vfs::ProxyFileSystem {
+public:
+ explicit VolatileFileSystem(llvm::IntrusiveRefCntPtr<FileSystem> FS)
+ : ProxyFileSystem(std::move(FS)) {}
+
+ llvm::ErrorOr<std::unique_ptr<vfs::File>>
+ openFileForRead(const Twine &InPath) override {
+ SmallString<128> Path;
+ InPath.toVector(Path);
+
+ auto File = getUnderlyingFS().openFileForRead(Path);
+ if (!File)
+ return File;
+ // Try to guess preamble files, they can be memory-mapped even on Windows as
+ // clangd has exclusive access to those.
+ StringRef FileName = llvm::sys::path::filename(Path);
+ if (FileName.startswith("preamble-") && FileName.endswith(".pch"))
+ return File;
+ return std::unique_ptr<VolatileFile>(
+ new VolatileFile(std::move(*File)));
+ }
+
+private:
+ class VolatileFile : public vfs::File {
+ public:
+ VolatileFile(std::unique_ptr<vfs::File> Wrapped)
+ : Wrapped(std::move(Wrapped)) {
+ assert(this->Wrapped);
+ }
+
+ virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool /*IsVolatile*/) override {
+ return Wrapped->getBuffer(Name, FileSize, RequiresNullTerminator,
+ /*IsVolatile=*/true);
+ }
+
+ llvm::ErrorOr<vfs::Status> status() override { return Wrapped->status(); }
+ llvm::ErrorOr<std::string> getName() override { return Wrapped->getName(); }
+ std::error_code close() override { return Wrapped->close(); }
+
+ private:
+ std::unique_ptr<File> Wrapped;
+ };
+};
+} // namespace
+
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+clang::clangd::RealFileSystemProvider::getFileSystem() const {
+// Avoid using memory-mapped files on Windows, they cause file locking issues.
+// FIXME: Try to use a similar approach in Sema instead of relying on
+// propagation of the 'isVolatile' flag through all layers.
+#ifdef _WIN32
+ return new VolatileFSProvider(vfs::getRealFileSystem());
+#else
+ return vfs::getRealFileSystem();
+#endif
+}
+} // namespace clangd
+} // namespace clang
diff --git a/clang-tools-extra/clangd/FSProvider.h b/clang-tools-extra/clangd/FSProvider.h
index a39758aed8a..67d2ec1508b 100644
--- a/clang-tools-extra/clangd/FSProvider.h
+++ b/clang-tools-extra/clangd/FSProvider.h
@@ -33,9 +33,7 @@ class RealFileSystemProvider : public FileSystemProvider {
public:
// FIXME: returns the single real FS instance, which is not threadsafe.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getFileSystem() const override {
- return llvm::vfs::getRealFileSystem();
- }
+ getFileSystem() const override;
};
} // namespace clangd
OpenPOWER on IntegriCloud