Summary: Main file can certainly change when reusing preamble.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D52991
llvm-svn: 344024
#include "clang/Serialization/ASTWriter.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/raw_ostream.h"
// dirs.
}
- auto StatCache = llvm::make_unique<PreambleFileStatusCache>();
+ llvm::SmallString<32> AbsFileName(FileName);
+ Inputs.FS->makeAbsolute(AbsFileName);
+ auto StatCache = llvm::make_unique<PreambleFileStatusCache>(AbsFileName);
auto BuiltPreamble = PrecompiledPreamble::Build(
CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
StatCache->getProducingFS(Inputs.FS), PCHs, StoreInMemory,
#include "FS.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/None.h"
+#include "llvm/Support/Path.h"
namespace clang {
namespace clangd {
+PreambleFileStatusCache::PreambleFileStatusCache(llvm::StringRef MainFilePath)
+ : MainFilePath(MainFilePath) {
+ assert(llvm::sys::path::is_absolute(MainFilePath));
+}
+
void PreambleFileStatusCache::update(const vfs::FileSystem &FS, vfs::Status S) {
SmallString<32> PathStore(S.getName());
if (FS.makeAbsolute(PathStore))
return;
+ // Do not cache status for the main file.
+ if (PathStore == MainFilePath)
+ return;
// Stores the latest status in cache as it can change in a preamble build.
StatCache.insert({PathStore, std::move(S)});
}
namespace clangd {
/// Records status information for files open()ed or stat()ed during preamble
-/// build, so we can avoid stat()s on the underlying FS when reusing the
-/// preamble. For example, code completion can re-stat files when getting FileID
-/// for source locations stored in preamble (e.g. checking whether a location is
-/// in the main file).
+/// build (except for the main file), so we can avoid stat()s on the underlying
+/// FS when reusing the preamble. For example, code completion can re-stat files
+/// when getting FileID for source locations stored in preamble (e.g. checking
+/// whether a location is in the main file).
///
/// The cache is keyed by absolute path of file name in cached status, as this
/// is what preamble stores.
/// Note that the cache is only valid when reusing preamble.
class PreambleFileStatusCache {
public:
+ /// \p MainFilePath is the absolute path of the main source file this preamble
+ /// corresponds to. The stat for the main file will not be cached.
+ PreambleFileStatusCache(llvm::StringRef MainFilePath);
+
void update(const vfs::FileSystem &FS, vfs::Status S);
+
/// \p Path is a path stored in preamble.
llvm::Optional<vfs::Status> lookup(llvm::StringRef Path) const;
getConsumingFS(IntrusiveRefCntPtr<vfs::FileSystem> FS) const;
private:
+ std::string MainFilePath;
llvm::StringMap<vfs::Status> StatCache;
};
llvm::StringMap<std::string> Files;
Files["x"] = "";
Files["y"] = "";
+ Files["main"] = "";
auto FS = buildTestFS(Files);
FS->setCurrentWorkingDirectory(testRoot());
- PreambleFileStatusCache StatCache;
+ PreambleFileStatusCache StatCache(testPath("main"));
auto ProduceFS = StatCache.getProducingFS(FS);
EXPECT_TRUE(ProduceFS->openFileForRead("x"));
EXPECT_TRUE(ProduceFS->status("y"));
+ EXPECT_TRUE(ProduceFS->status("main"));
EXPECT_TRUE(StatCache.lookup(testPath("x")).hasValue());
EXPECT_TRUE(StatCache.lookup(testPath("y")).hasValue());
+ // Main file is not cached.
+ EXPECT_FALSE(StatCache.lookup(testPath("main")).hasValue());
vfs::Status S("fake", llvm::sys::fs::UniqueID(0, 0),
std::chrono::system_clock::now(), 0, 0, 1024,