9#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
10#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
14#include "llvm/ADT/DenseSet.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;
158 llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator>
162 llvm::DenseMap<llvm::sys::fs::UniqueID, const CachedFileSystemEntry *>
183 llvm::ErrorOr<llvm::vfs::Status> Stat);
190 std::unique_ptr<llvm::MemoryBuffer> Contents);
206 std::unique_ptr<CacheShard[]> CacheShards;
213 llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator>
Cache;
219 return It ==
Cache.end() ? nullptr : It->getValue();
227 const auto *InsertedEntry =
Cache.insert({
Filename, &Entry}).first->second;
228 assert(InsertedEntry == &Entry &&
"entry already present");
229 return *InsertedEntry;
238 std::string Filename;
248 llvm::vfs::Status Stat = Entry.
getStatus();
249 if (!Stat.isDirectory())
250 Stat = llvm::vfs::Status::copyWithNewSize(Stat,
getContents().size());
251 return llvm::vfs::Status::copyWithNewName(Stat,
Filename);
266 std::optional<ArrayRef<dependency_directives_scan::Directive>>
286 : ProxyFileSystem(
std::move(FS)), SharedCache(SharedCache) {}
288 llvm::ErrorOr<llvm::vfs::Status>
status(
const Twine &Path)
override;
289 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
296 llvm::ErrorOr<EntryRef>
298 bool DisableDirectivesScanning =
false);
302 bool shouldScanForDirectives(StringRef
Filename);
307 llvm::ErrorOr<const CachedFileSystemEntry &>
308 computeAndStoreResult(StringRef
Filename);
317 struct TentativeEntry {
318 llvm::vfs::Status Status;
319 std::unique_ptr<llvm::MemoryBuffer> Contents;
321 TentativeEntry(llvm::vfs::Status Status,
322 std::unique_ptr<llvm::MemoryBuffer> Contents =
nullptr)
323 : Status(
std::move(Status)), Contents(
std::move(Contents)) {}
328 llvm::ErrorOr<TentativeEntry> readFile(StringRef
Filename);
333 const CachedFileSystemEntry &
334 getOrEmplaceSharedEntryForUID(TentativeEntry TEntry);
341 const CachedFileSystemEntry *
342 findEntryByFilenameWithWriteThrough(StringRef
Filename);
346 const CachedFileSystemEntry *
347 findSharedEntryByUID(llvm::vfs::Status Stat)
const {
354 const CachedFileSystemEntry &
355 insertLocalEntryForFilename(StringRef
Filename,
356 const CachedFileSystemEntry &Entry) {
363 const CachedFileSystemEntry &
364 getOrEmplaceSharedEntryForFilename(StringRef
Filename, std::error_code EC) {
372 const CachedFileSystemEntry &
373 getOrInsertSharedEntryForFilename(StringRef
Filename,
374 const CachedFileSystemEntry &Entry) {
379 void printImpl(raw_ostream &OS, PrintType Type,
380 unsigned IndentLevel)
const override {
381 printIndent(OS, IndentLevel);
382 OS <<
"DependencyScanningFilesystem\n";
383 getUnderlyingFS().print(OS, Type, IndentLevel + 1);
387 DependencyScanningFilesystemSharedCache &SharedCache;
390 DependencyScanningFilesystemLocalCache LocalCache;
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.
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