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"
24namespace dependencies {
43 std::atomic<const std::optional<DependencyDirectivesTy> *>
DepDirectives;
65 : MaybeStat(
std::move(Stat)), Contents(nullptr) {
72 : MaybeStat(
std::move(Stat)), Contents(
std::move(Contents)) {
77 bool isError()
const {
return !MaybeStat; }
85 assert(!MaybeStat->isDirectory() &&
"not a file");
86 assert(Contents &&
"contents not initialized");
87 return Contents->
Original->getBuffer();
92 std::optional<ArrayRef<dependency_directives_scan::Directive>>
96 assert(Contents &&
"contents not initialized");
98 if (Directives->has_value())
105 std::error_code
getError()
const {
return MaybeStat.getError(); }
110 assert(MaybeStat->getName().empty() &&
"stat name must be empty");
117 return MaybeStat->getUniqueID();
128 void clearStatName() {
130 MaybeStat = llvm::vfs::Status::copyWithNewName(*MaybeStat,
"");
135 llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
142 CachedFileContents *Contents;
161 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
162 llvm::BumpPtrAllocator>
166 llvm::DenseMap<llvm::sys::fs::UniqueID, const CachedFileSystemEntry *>
190 llvm::ErrorOr<llvm::vfs::Status> Stat);
197 std::unique_ptr<llvm::MemoryBuffer> Contents);
214 llvm::ErrorOr<StringRef> RealPath);
224 std::unique_ptr<CacheShard[]> CacheShards;
232 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
233 llvm::BumpPtrAllocator>
239 assert(llvm::sys::path::is_absolute_gnu(
Filename));
241 return It ==
Cache.end() ? nullptr : It->getValue().first;
249 assert(llvm::sys::path::is_absolute_gnu(
Filename));
250 auto [It, Inserted] =
Cache.insert({
Filename, {&Entry,
nullptr}});
255 assert((!CachedEntry &&
CachedRealPath) &&
"entry already present");
256 CachedEntry = &Entry;
264 assert(llvm::sys::path::is_absolute_gnu(
Filename));
266 return It ==
Cache.end() ? nullptr : It->getValue().second;
274 assert(llvm::sys::path::is_absolute_gnu(
Filename));
275 auto [It, Inserted] =
Cache.insert({
Filename, {
nullptr, &RealPath}});
280 assert((!
CachedRealPath && CachedEntry) &&
"real path already present");
292 std::string Filename;
304 llvm::vfs::Status Stat = Entry.
getStatus();
305 if (!Stat.isDirectory())
306 Stat = llvm::vfs::Status::copyWithNewSize(Stat,
getContents().size());
307 return llvm::vfs::Status::copyWithNewName(Stat,
Filename);
322 std::optional<ArrayRef<dependency_directives_scan::Directive>>
338 :
public llvm::RTTIExtends<DependencyScanningWorkerFilesystem,
339 llvm::vfs::ProxyFileSystem> {
341 static const char ID;
347 llvm::ErrorOr<llvm::vfs::Status>
status(
const Twine &
Path)
override;
348 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
384 llvm::ErrorOr<const CachedFileSystemEntry &>
385 computeAndStoreResult(StringRef OriginalFilename,
386 StringRef FilenameForLookup);
390 struct TentativeEntry {
391 llvm::vfs::Status Status;
392 std::unique_ptr<llvm::MemoryBuffer> Contents;
394 TentativeEntry(llvm::vfs::Status Status,
395 std::unique_ptr<llvm::MemoryBuffer> Contents =
nullptr)
396 : Status(
std::move(Status)), Contents(
std::move(Contents)) {}
401 llvm::ErrorOr<TentativeEntry> readFile(StringRef
Filename);
406 const CachedFileSystemEntry &
407 getOrEmplaceSharedEntryForUID(TentativeEntry TEntry);
414 const CachedFileSystemEntry *
415 findEntryByFilenameWithWriteThrough(StringRef
Filename);
419 const CachedFileSystemEntry *
420 findSharedEntryByUID(llvm::vfs::Status Stat)
const {
427 const CachedFileSystemEntry &
428 insertLocalEntryForFilename(StringRef
Filename,
429 const CachedFileSystemEntry &Entry) {
436 const CachedFileSystemEntry &
437 getOrEmplaceSharedEntryForFilename(StringRef
Filename, std::error_code EC) {
445 const CachedFileSystemEntry &
446 getOrInsertSharedEntryForFilename(StringRef
Filename,
447 const CachedFileSystemEntry &Entry) {
452 void printImpl(raw_ostream &OS, PrintType Type,
453 unsigned IndentLevel)
const override {
454 printIndent(OS, IndentLevel);
455 OS <<
"DependencyScanningFilesystem\n";
456 getUnderlyingFS().print(OS, Type, IndentLevel + 1);
461 bool shouldBypass(StringRef
Path)
const;
464 DependencyScanningFilesystemSharedCache &SharedCache;
467 DependencyScanningFilesystemLocalCache LocalCache;
470 std::optional<std::string> BypassedPathPrefix;
474 llvm::ErrorOr<std::string> WorkingDirForCacheLookup;
476 void updateWorkingDirForCacheLookup();
478 llvm::ErrorOr<StringRef>
479 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