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;
61 this->FS = llvm::vfs::getRealFileSystem();
67 assert(statCache &&
"No stat cache provided?");
68 StatCache = std::move(statCache);
81 if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
84 StringRef DirName = llvm::sys::path::parent_path(Filename);
94 void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
95 StringRef DirName = llvm::sys::path::parent_path(Path);
100 *SeenDirEntries.insert(std::make_pair(DirName,
nullptr)).first;
110 auto UDE = llvm::make_unique<DirectoryEntry>();
111 UDE->Name = NamedDirEnt.first();
112 NamedDirEnt.second = UDE.get();
113 VirtualDirectoryEntries.push_back(std::move(UDE));
116 addAncestorsAsVirtualDirs(DirName);
124 if (DirName.size() > 1 &&
125 DirName != llvm::sys::path::root_path(DirName) &&
126 llvm::sys::path::is_separator(DirName.back()))
127 DirName = DirName.substr(0, DirName.size()-1);
131 std::string DirNameStr;
132 if (DirName.size() > 1 && DirName.back() ==
':' &&
133 DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
134 DirNameStr = DirName.str() +
'.';
135 DirName = DirNameStr;
141 *SeenDirEntries.insert(std::make_pair(DirName,
nullptr)).first;
145 if (NamedDirEnt.second)
147 : NamedDirEnt.second;
156 StringRef InterndDirName = NamedDirEnt.first();
160 if (getStatValue(InterndDirName, Data,
false,
nullptr )) {
163 SeenDirEntries.erase(DirName);
173 NamedDirEnt.second = &UDE;
177 UDE.Name = InterndDirName;
189 *SeenFileEntries.insert(std::make_pair(Filename,
nullptr)).first;
192 if (NamedFileEnt.second) {
196 if (!(NamedFileEnt.second->DeferredOpen && openFile))
197 return NamedFileEnt.second;
205 ++NumFileCacheMisses;
209 StringRef InterndFileName = NamedFileEnt.first();
218 if (DirInfo ==
nullptr) {
220 SeenFileEntries.erase(Filename);
229 std::unique_ptr<llvm::vfs::File> F;
231 if (getStatValue(InterndFileName, Data,
true, openFile ? &F :
nullptr)) {
234 SeenFileEntries.erase(Filename);
239 assert((openFile || !F) &&
"undesired open file");
244 UFE.DeferredOpen = !openFile;
246 NamedFileEnt.second = &UFE;
250 if (Data.
Name != Filename) {
252 *SeenFileEntries.insert(std::make_pair(Data.
Name,
nullptr)).first;
253 if (!NamedFileEnt.second)
254 NamedFileEnt.second = &UFE;
256 assert(NamedFileEnt.second == &UFE &&
257 "filename from getStatValue() refers to wrong file");
258 InterndFileName = NamedFileEnt.first().data();
263 if (F && !UFE.File) {
264 if (
auto PathName = F->getName())
265 fillRealPathName(&UFE, *PathName);
266 UFE.File = std::move(F);
267 assert(!UFE.DeferredOpen &&
"we just opened it!");
286 UFE.Name = InterndFileName;
292 UFE.Name = InterndFileName;
293 UFE.Size = Data.
Size;
296 UFE.UID = NextFileUID++;
299 UFE.InPCH = Data.
InPCH;
308 time_t ModificationTime) {
313 *SeenFileEntries.insert(std::make_pair(Filename,
nullptr)).first;
317 return NamedFileEnt.second;
319 ++NumFileCacheMisses;
324 addAncestorsAsVirtualDirs(Filename);
333 "The directory of a virtual file should already be in the cache.");
337 const char *InterndFileName = NamedFileEnt.first().data();
338 if (getStatValue(InterndFileName, Data,
true,
nullptr) == 0) {
340 Data.
ModTime = ModificationTime;
341 UFE = &UniqueRealFiles[Data.
UniqueID];
343 NamedFileEnt.second = UFE;
357 UFE->InPCH = Data.
InPCH;
358 fillRealPathName(UFE, Data.
Name);
362 VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
363 UFE = VirtualFileEntries.back().get();
364 NamedFileEnt.second = UFE;
367 UFE->Name = InterndFileName;
369 UFE->ModTime = ModificationTime;
371 UFE->UID = NextFileUID++;
374 UFE->DeferredOpen =
false;
379 StringRef pathRef(path.data(), path.size());
382 || llvm::sys::path::is_absolute(pathRef))
386 llvm::sys::path::append(NewPath, pathRef);
394 if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
395 FS->makeAbsolute(Path);
402 void FileManager::fillRealPathName(
FileEntry *UFE, llvm::StringRef FileName) {
409 llvm::sys::path::remove_dots(AbsPath,
true);
410 UFE->RealPathName = AbsPath.str();
413 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
415 bool ShouldCloseOpenFile) {
416 uint64_t FileSize = Entry->
getSize();
426 Entry->File->getBuffer(Filename, FileSize,
430 if (ShouldCloseOpenFile)
438 return FS->getBufferForFile(Filename, FileSize,
443 return FS->getBufferForFile(FilePath, FileSize,
447 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
450 return FS->getBufferForFile(Filename, -1,
true, isVolatile);
454 return FS->getBufferForFile(FilePath.c_str(), -1,
true, isVolatile);
462 bool FileManager::getStatValue(StringRef Path,
FileData &Data,
bool isFile,
463 std::unique_ptr<llvm::vfs::File> *F) {
473 StatCache.get(), *FS);
477 llvm::vfs::Status &
Result) {
481 llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str());
489 assert(Entry &&
"Cannot invalidate a NULL FileEntry");
491 SeenFileEntries.erase(Entry->
getName());
502 UIDToFiles.resize(NextFileUID);
505 for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
506 FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
509 UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
512 for (
const auto &VFE : VirtualFileEntries)
514 UIDToFiles[VFE->getUID()] = VFE.get();
518 off_t Size, time_t ModificationTime) {
520 File->ModTime = ModificationTime;
525 llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
526 = CanonicalDirNames.find(Dir);
527 if (Known != CanonicalDirNames.end())
528 return Known->second;
530 StringRef CanonicalName(Dir->
getName());
533 if (!FS->getRealPath(Dir->
getName(), CanonicalNameBuf))
534 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
536 CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
537 return CanonicalName;
541 llvm::errs() <<
"\n*** File Manager Stats:\n";
542 llvm::errs() << UniqueRealFiles.size() <<
" real files found, " 543 << UniqueRealDirs.size() <<
" real dirs found.\n";
544 llvm::errs() << VirtualFileEntries.size() <<
" virtual files found, " 545 << VirtualDirectoryEntries.size() <<
" virtual dirs found.\n";
546 llvm::errs() << NumDirLookups <<
" dir lookups, " 547 << NumDirCacheMisses <<
" dir cache misses.\n";
548 llvm::errs() << NumFileLookups <<
" file lookups, " 549 << 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.
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.
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...
FileManager(const FileSystemOptions &FileSystemOpts, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=nullptr)
#define NON_EXISTENT_FILE
NON_EXISTENT_FILE - A special value distinct from null that is used to represent a filename that does...
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.
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.
static bool get(StringRef Path, FileData &Data, bool isFile, std::unique_ptr< llvm::vfs::File > *F, FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS)
Get the 'stat' information for the specified path, using the cache to accelerate it if possible...
llvm::sys::fs::UniqueID UniqueID
StringRef getName() const
Cached information about one file (either on disk or in the virtual file system). ...
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 clearStatCache()
Removes the 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.
bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result)
Get the 'stat' information for the given Path.
Cached information about one directory (either on disk or in the virtual file system).
void setStatCache(std::unique_ptr< FileSystemStatCache > statCache)
Installs the provided FileSystemStatCache object within the FileManager.
Keeps track of options that affect how file operations are performed.
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.
StringRef getName() const