22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/Config/llvm-config.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/Support/FileSystem.h" 26 #include "llvm/Support/MemoryBuffer.h" 27 #include "llvm/Support/Path.h" 28 #include "llvm/Support/raw_ostream.h" 37 using namespace clang;
41 #define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 45 #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 53 : FS(
std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64),
54 SeenFileEntries(64), NextFileUID(0) {
55 NumDirLookups = NumFileLookups = 0;
56 NumDirCacheMisses = NumFileCacheMisses = 0;
68 assert(statCache &&
"No stat cache provided?");
69 if (AtBeginning || !StatCache.get()) {
70 statCache->setNextStatCache(std::move(StatCache));
71 StatCache = std::move(statCache);
86 if (StatCache.get() == statCache) {
88 StatCache = StatCache->takeNextStatCache();
97 assert(PrevCache &&
"Stat cache not found for removal");
110 if (Filename.empty())
113 if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
116 StringRef DirName = llvm::sys::path::parent_path(Filename);
126 void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
127 StringRef DirName = llvm::sys::path::parent_path(Path);
132 *SeenDirEntries.insert(std::make_pair(DirName,
nullptr)).first;
142 auto UDE = llvm::make_unique<DirectoryEntry>();
143 UDE->Name = NamedDirEnt.first();
144 NamedDirEnt.second = UDE.get();
145 VirtualDirectoryEntries.push_back(std::move(UDE));
148 addAncestorsAsVirtualDirs(DirName);
156 if (DirName.size() > 1 &&
157 DirName != llvm::sys::path::root_path(DirName) &&
158 llvm::sys::path::is_separator(DirName.back()))
159 DirName = DirName.substr(0, DirName.size()-1);
163 std::string DirNameStr;
164 if (DirName.size() > 1 && DirName.back() ==
':' &&
165 DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
166 DirNameStr = DirName.str() +
'.';
167 DirName = DirNameStr;
173 *SeenDirEntries.insert(std::make_pair(DirName,
nullptr)).first;
177 if (NamedDirEnt.second)
179 : NamedDirEnt.second;
188 StringRef InterndDirName = NamedDirEnt.first();
192 if (getStatValue(InterndDirName, Data,
false,
nullptr )) {
195 SeenDirEntries.erase(DirName);
205 NamedDirEnt.second = &UDE;
209 UDE.Name = InterndDirName;
221 *SeenFileEntries.insert(std::make_pair(Filename,
nullptr)).first;
224 if (NamedFileEnt.second)
226 : NamedFileEnt.second;
228 ++NumFileCacheMisses;
235 StringRef InterndFileName = NamedFileEnt.first();
244 if (DirInfo ==
nullptr) {
246 SeenFileEntries.erase(Filename);
255 std::unique_ptr<vfs::File> F;
257 if (getStatValue(InterndFileName, Data,
true, openFile ? &F :
nullptr)) {
260 SeenFileEntries.erase(Filename);
265 assert((openFile || !F) &&
"undesired open file");
271 NamedFileEnt.second = &UFE;
275 if (Data.
Name != Filename) {
277 *SeenFileEntries.insert(std::make_pair(Data.
Name,
nullptr)).first;
278 if (!NamedFileEnt.second)
279 NamedFileEnt.second = &UFE;
281 assert(NamedFileEnt.second == &UFE &&
282 "filename from getStatValue() refers to wrong file");
283 InterndFileName = NamedFileEnt.first().data();
302 UFE.Name = InterndFileName;
308 UFE.Name = InterndFileName;
309 UFE.Size = Data.
Size;
312 UFE.UID = NextFileUID++;
315 UFE.InPCH = Data.
InPCH;
316 UFE.File = std::move(F);
319 if (
auto RealPathName = UFE.File->getName())
320 UFE.RealPathName = *RealPathName;
326 time_t ModificationTime) {
331 *SeenFileEntries.insert(std::make_pair(Filename,
nullptr)).first;
335 return NamedFileEnt.second;
337 ++NumFileCacheMisses;
342 addAncestorsAsVirtualDirs(Filename);
351 "The directory of a virtual file should already be in the cache.");
355 const char *InterndFileName = NamedFileEnt.first().data();
356 if (getStatValue(InterndFileName, Data,
true,
nullptr) == 0) {
358 Data.
ModTime = ModificationTime;
359 UFE = &UniqueRealFiles[Data.
UniqueID];
361 NamedFileEnt.second = UFE;
375 UFE->InPCH = Data.
InPCH;
379 VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
380 UFE = VirtualFileEntries.back().get();
381 NamedFileEnt.second = UFE;
384 UFE->Name = InterndFileName;
386 UFE->ModTime = ModificationTime;
388 UFE->UID = NextFileUID++;
395 StringRef pathRef(path.data(), path.size());
398 || llvm::sys::path::is_absolute(pathRef))
402 llvm::sys::path::append(NewPath, pathRef);
410 if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
411 FS->makeAbsolute(Path);
418 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
420 bool ShouldCloseOpenFile) {
421 uint64_t FileSize = Entry->
getSize();
431 Entry->File->getBuffer(Filename, FileSize,
435 if (ShouldCloseOpenFile)
443 return FS->getBufferForFile(Filename, FileSize,
448 return FS->getBufferForFile(FilePath, FileSize,
452 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
455 return FS->getBufferForFile(Filename);
459 return FS->getBufferForFile(FilePath.c_str());
467 bool FileManager::getStatValue(StringRef Path,
FileData &Data,
bool isFile,
468 std::unique_ptr<vfs::File> *F) {
478 StatCache.get(), *FS);
486 llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str());
494 assert(Entry &&
"Cannot invalidate a NULL FileEntry");
496 SeenFileEntries.erase(Entry->
getName());
507 UIDToFiles.resize(NextFileUID);
510 for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
511 FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
514 UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
517 for (
const auto &VFE : VirtualFileEntries)
519 UIDToFiles[VFE->getUID()] = VFE.get();
523 off_t Size, time_t ModificationTime) {
525 File->ModTime = ModificationTime;
530 llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
531 = CanonicalDirNames.find(Dir);
532 if (Known != CanonicalDirNames.end())
533 return Known->second;
535 StringRef CanonicalName(Dir->
getName());
538 char CanonicalNameBuf[PATH_MAX];
539 if (realpath(Dir->
getName().str().c_str(), CanonicalNameBuf))
540 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
543 llvm::sys::fs::make_absolute(CanonicalNameBuf);
544 llvm::sys::path::native(CanonicalNameBuf);
551 llvm::sys::path::remove_dots(CanonicalNameBuf,
true);
552 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
555 CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
556 return CanonicalName;
560 llvm::errs() <<
"\n*** File Manager Stats:\n";
561 llvm::errs() << UniqueRealFiles.size() <<
" real files found, " 562 << UniqueRealDirs.size() <<
" real dirs found.\n";
563 llvm::errs() << VirtualFileEntries.size() <<
" virtual files found, " 564 << VirtualDirectoryEntries.size() <<
" virtual dirs found.\n";
565 llvm::errs() << NumDirLookups <<
" dir lookups, " 566 << NumDirCacheMisses <<
" dir cache misses.\n";
567 llvm::errs() << NumFileLookups <<
" file lookups, " 568 << NumFileCacheMisses <<
" file cache misses.\n";
Implements support for file system lookup, file system caching, and directory search management...
Defines the clang::FileManager interface and associated types.
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
void GetUniqueIDMapping(SmallVectorImpl< const FileEntry *> &UIDToFiles) const
Produce an array mapping from the unique IDs assigned to each file to the corresponding FileEntry poi...
Defines the FileSystemStatCache interface.
FileManager(const FileSystemOptions &FileSystemOpts, IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr)
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option...
const llvm::sys::fs::UniqueID & getUniqueID() const
#define NON_EXISTENT_DIR
NON_EXISTENT_DIR - A special value distinct from null that is used to represent a dir name that doesn...
#define NON_EXISTENT_FILE
NON_EXISTENT_FILE - A special value distinct from null that is used to represent a filename that does...
Abstract interface for introducing a FileManager cache for 'stat' system calls, which is used by prec...
std::unique_ptr< FileSystemStatCache > takeNextStatCache()
Retrieve the next stat call cache in the chain, transferring ownership of this cache (and...
The result of a status operation.
static bool get(StringRef Path, FileData &Data, bool isFile, std::unique_ptr< vfs::File > *F, FileSystemStatCache *Cache, vfs::FileSystem &FS)
Get the 'stat' information for the specified path, using the cache to accelerate it if possible...
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
const DirectoryEntry * getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
bool FixupRelativePath(SmallVectorImpl< char > &path) const
If path is not absolute and FileSystemOptions set the working directory, the path is modified to be r...
static const DirectoryEntry * getDirectoryFromFile(FileManager &FileMgr, StringRef Filename, bool CacheFailure)
Retrieve the directory that the given file name resides in.
void setNextStatCache(std::unique_ptr< FileSystemStatCache > Cache)
Sets the next stat call cache in the chain of stat caches.
std::string WorkingDir
If set, paths are resolved as if the working directory was set to the value of WorkingDir.
The result type of a method or function.
void addStatCache(std::unique_ptr< FileSystemStatCache > statCache, bool AtBeginning=false)
Installs the provided FileSystemStatCache object within the FileManager.
llvm::sys::fs::UniqueID UniqueID
StringRef getName() const
Cached information about one file (either on disk or in the virtual file system). ...
void clearStatCaches()
Removes all FileSystemStatCache objects from the manager.
const FileEntry * getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime)
Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...
StringRef getCanonicalName(const DirectoryEntry *Dir)
Retrieve the canonical name for a given directory.
Dataflow Directional Tag Classes.
void removeStatCache(FileSystemStatCache *statCache)
Removes the specified FileSystemStatCache object from the manager.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool ShouldCloseOpenFile=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
Cached information about one directory (either on disk or in the virtual file system).
Keeps track of options that affect how file operations are performed.
bool getNoncachedStatValue(StringRef Path, vfs::Status &Result)
Get the 'stat' information for the given Path.
static void modifyFileEntry(FileEntry *File, off_t Size, time_t ModificationTime)
Modifies the size and modification time of a previously created FileEntry.
void invalidateCache(const FileEntry *Entry)
Remove the real file Entry from the cache.
FileSystemStatCache * getNextStatCache()
Retrieve the next stat call cache in the chain.
StringRef getName() const