9#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
10#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/StringMap.h"
16#include "llvm/Support/Allocator.h"
17#include "llvm/Support/ErrorOr.h"
18#include "llvm/Support/VirtualFileSystem.h"
25namespace dependencies {
44 std::atomic<const std::optional<DependencyDirectivesTy> *>
DepDirectives;
66 : MaybeStat(
std::move(Stat)), Contents(nullptr) {
73 : MaybeStat(
std::move(Stat)), Contents(
std::move(Contents)) {
78 bool isError()
const {
return !MaybeStat; }
86 assert(!MaybeStat->isDirectory() &&
"not a file");
87 assert(Contents &&
"contents not initialized");
88 return Contents->
Original->getBuffer();
93 std::optional<ArrayRef<dependency_directives_scan::Directive>>
97 assert(Contents &&
"contents not initialized");
99 if (Directives->has_value())
106 std::error_code
getError()
const {
return MaybeStat.getError(); }
111 assert(MaybeStat->getName().empty() &&
"stat name must be empty");
118 return MaybeStat->getUniqueID();
129 void clearStatName() {
131 MaybeStat = llvm::vfs::Status::copyWithNewName(*MaybeStat,
"");
136 llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
143 CachedFileContents *Contents;
162 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
163 llvm::BumpPtrAllocator>
167 llvm::DenseMap<llvm::sys::fs::UniqueID, const CachedFileSystemEntry *>
191 llvm::ErrorOr<llvm::vfs::Status> Stat);
198 std::unique_ptr<llvm::MemoryBuffer> Contents);
215 llvm::ErrorOr<StringRef> RealPath);
234 std::variant<NegativelyCachedInfo, SizeChangedInfo>
Info;
250 std::vector<OutOfDateEntry>
254 std::unique_ptr<CacheShard[]> CacheShards;
262 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
263 llvm::BumpPtrAllocator>
269 assert(llvm::sys::path::is_absolute_gnu(
Filename));
271 return It ==
Cache.end() ? nullptr : It->getValue().first;
279 assert(llvm::sys::path::is_absolute_gnu(
Filename));
280 auto [It, Inserted] =
Cache.insert({
Filename, {&Entry,
nullptr}});
285 assert((!CachedEntry &&
CachedRealPath) &&
"entry already present");
286 CachedEntry = &Entry;
294 assert(llvm::sys::path::is_absolute_gnu(
Filename));
296 return It ==
Cache.end() ? nullptr : It->getValue().second;
304 assert(llvm::sys::path::is_absolute_gnu(
Filename));
305 auto [It, Inserted] =
Cache.insert({
Filename, {
nullptr, &RealPath}});
310 assert((!
CachedRealPath && CachedEntry) &&
"real path already present");
322 std::string Filename;
334 llvm::vfs::Status Stat = Entry.
getStatus();
335 if (!Stat.isDirectory())
336 Stat = llvm::vfs::Status::copyWithNewSize(Stat,
getContents().size());
337 return llvm::vfs::Status::copyWithNewName(Stat,
Filename);
352 std::optional<ArrayRef<dependency_directives_scan::Directive>>
368 :
public llvm::RTTIExtends<DependencyScanningWorkerFilesystem,
369 llvm::vfs::ProxyFileSystem> {
371 static const char ID;
377 llvm::ErrorOr<llvm::vfs::Status>
status(
const Twine &
Path)
override;
378 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
406 std::optional<ArrayRef<dependency_directives_scan::Directive>>
410 return Entry->getDirectiveTokens();
424 llvm::ErrorOr<const CachedFileSystemEntry &>
425 computeAndStoreResult(StringRef OriginalFilename,
426 StringRef FilenameForLookup);
430 struct TentativeEntry {
431 llvm::vfs::Status Status;
432 std::unique_ptr<llvm::MemoryBuffer> Contents;
434 TentativeEntry(llvm::vfs::Status Status,
435 std::unique_ptr<llvm::MemoryBuffer> Contents =
nullptr)
436 : Status(
std::move(Status)), Contents(
std::move(Contents)) {}
441 llvm::ErrorOr<TentativeEntry> readFile(StringRef
Filename);
446 const CachedFileSystemEntry &
447 getOrEmplaceSharedEntryForUID(TentativeEntry TEntry);
454 const CachedFileSystemEntry *
455 findEntryByFilenameWithWriteThrough(StringRef
Filename);
459 const CachedFileSystemEntry *
460 findSharedEntryByUID(llvm::vfs::Status Stat)
const {
467 const CachedFileSystemEntry &
468 insertLocalEntryForFilename(StringRef
Filename,
469 const CachedFileSystemEntry &Entry) {
476 const CachedFileSystemEntry &
477 getOrEmplaceSharedEntryForFilename(StringRef
Filename, std::error_code EC) {
485 const CachedFileSystemEntry &
486 getOrInsertSharedEntryForFilename(StringRef
Filename,
487 const CachedFileSystemEntry &Entry) {
492 void printImpl(raw_ostream &OS, PrintType Type,
493 unsigned IndentLevel)
const override {
494 printIndent(OS, IndentLevel);
495 OS <<
"DependencyScanningFilesystem\n";
496 getUnderlyingFS().print(OS, Type, IndentLevel + 1);
501 bool shouldBypass(StringRef
Path)
const;
504 DependencyScanningFilesystemSharedCache &SharedCache;
507 DependencyScanningFilesystemLocalCache LocalCache;
510 std::optional<std::string> BypassedPathPrefix;
514 llvm::ErrorOr<std::string> WorkingDirForCacheLookup;
516 void updateWorkingDirForCacheLookup();
518 llvm::ErrorOr<StringRef>
519 tryGetFilenameForLookup(StringRef OriginalFilename,
This is the interface for scanning header and source files to get the minimum necessary preprocessor ...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
TypePropertyCache< Private > Cache
An in-memory representation of a file system entity that is of interest to the dependency scanning fi...
std::error_code getError() const
CachedFileSystemEntry(llvm::ErrorOr< llvm::vfs::Status > Stat)
Creates an entry without contents: either a filesystem error or a directory with stat value.
llvm::sys::fs::UniqueID getUniqueID() const
CachedFileContents * getCachedContents() const
CachedFileSystemEntry(llvm::ErrorOr< llvm::vfs::Status > Stat, CachedFileContents *Contents)
Creates an entry representing a file with contents.
StringRef getOriginalContents() const
llvm::vfs::Status getStatus() const
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens() const
Reference to a CachedFileSystemEntry.
EntryRef(StringRef Name, const CachedFileSystemEntry &Entry)
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens() const
llvm::vfs::Status getStatus() const
StringRef getContents() const
llvm::ErrorOr< EntryRef > unwrapError() const
If the cached entry represents an error, promotes it into ErrorOr.
The JSON file list parser is used to communicate input to InstallAPI.
Contents and directive tokens of a cached file entry.
std::mutex ValueLock
The mutex that must be locked before mutating directive tokens.
std::atomic< const std::optional< DependencyDirectivesTy > * > DepDirectives
Accessor to the directive tokens that's atomic to avoid data races.
CachedFileContents(std::unique_ptr< llvm::MemoryBuffer > Contents)
std::unique_ptr< llvm::MemoryBuffer > Original
Owning storage for the original contents.
SmallVector< dependency_directives_scan::Token, 10 > DepDirectiveTokens
OutOfDateEntry(const char *Path)
OutOfDateEntry(const char *Path, uint64_t CachedSize, uint64_t ActualSize)
std::variant< NegativelyCachedInfo, SizeChangedInfo > Info