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)
194 : NamedFileEnt.second;
196 ++NumFileCacheMisses;
203 StringRef InterndFileName = NamedFileEnt.first();
212 if (DirInfo ==
nullptr) {
214 SeenFileEntries.erase(Filename);
223 std::unique_ptr<llvm::vfs::File> F;
225 if (getStatValue(InterndFileName, Data,
true, openFile ? &F :
nullptr)) {
228 SeenFileEntries.erase(Filename);
233 assert((openFile || !F) &&
"undesired open file");
239 NamedFileEnt.second = &UFE;
243 if (Data.
Name != Filename) {
245 *SeenFileEntries.insert(std::make_pair(Data.
Name,
nullptr)).first;
246 if (!NamedFileEnt.second)
247 NamedFileEnt.second = &UFE;
249 assert(NamedFileEnt.second == &UFE &&
250 "filename from getStatValue() refers to wrong file");
251 InterndFileName = NamedFileEnt.first().data();
270 UFE.Name = InterndFileName;
276 UFE.Name = InterndFileName;
277 UFE.Size = Data.
Size;
280 UFE.UID = NextFileUID++;
283 UFE.InPCH = Data.
InPCH;
284 UFE.File = std::move(F);
288 if (
auto PathName = UFE.File->getName())
289 fillRealPathName(&UFE, *PathName);
296 time_t ModificationTime) {
301 *SeenFileEntries.insert(std::make_pair(Filename,
nullptr)).first;
305 return NamedFileEnt.second;
307 ++NumFileCacheMisses;
312 addAncestorsAsVirtualDirs(Filename);
321 "The directory of a virtual file should already be in the cache.");
325 const char *InterndFileName = NamedFileEnt.first().data();
326 if (getStatValue(InterndFileName, Data,
true,
nullptr) == 0) {
328 Data.
ModTime = ModificationTime;
329 UFE = &UniqueRealFiles[Data.
UniqueID];
331 NamedFileEnt.second = UFE;
345 UFE->InPCH = Data.
InPCH;
346 fillRealPathName(UFE, Data.
Name);
350 VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
351 UFE = VirtualFileEntries.back().get();
352 NamedFileEnt.second = UFE;
355 UFE->Name = InterndFileName;
357 UFE->ModTime = ModificationTime;
359 UFE->UID = NextFileUID++;
366 StringRef pathRef(path.data(), path.size());
369 || llvm::sys::path::is_absolute(pathRef))
373 llvm::sys::path::append(NewPath, pathRef);
381 if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
382 FS->makeAbsolute(Path);
389 void FileManager::fillRealPathName(
FileEntry *UFE, llvm::StringRef FileName) {
396 llvm::sys::path::remove_dots(AbsPath,
true);
397 UFE->RealPathName = AbsPath.str();
400 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
402 bool ShouldCloseOpenFile) {
403 uint64_t FileSize = Entry->
getSize();
413 Entry->File->getBuffer(Filename, FileSize,
417 if (ShouldCloseOpenFile)
425 return FS->getBufferForFile(Filename, FileSize,
430 return FS->getBufferForFile(FilePath, FileSize,
434 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
437 return FS->getBufferForFile(Filename, -1,
true, isVolatile);
441 return FS->getBufferForFile(FilePath.c_str(), -1,
true, isVolatile);
449 bool FileManager::getStatValue(StringRef Path,
FileData &Data,
bool isFile,
450 std::unique_ptr<llvm::vfs::File> *F) {
460 StatCache.get(), *FS);
464 llvm::vfs::Status &
Result) {
468 llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str());
476 assert(Entry &&
"Cannot invalidate a NULL FileEntry");
478 SeenFileEntries.erase(Entry->
getName());
489 UIDToFiles.resize(NextFileUID);
492 for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
493 FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
496 UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
499 for (
const auto &VFE : VirtualFileEntries)
501 UIDToFiles[VFE->getUID()] = VFE.get();
505 off_t Size, time_t ModificationTime) {
507 File->ModTime = ModificationTime;
512 llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
513 = CanonicalDirNames.find(Dir);
514 if (Known != CanonicalDirNames.end())
515 return Known->second;
517 StringRef CanonicalName(Dir->
getName());
520 if (!FS->getRealPath(Dir->
getName(), CanonicalNameBuf))
521 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
523 CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
524 return CanonicalName;
528 llvm::errs() <<
"\n*** File Manager Stats:\n";
529 llvm::errs() << UniqueRealFiles.size() <<
" real files found, " 530 << UniqueRealDirs.size() <<
" real dirs found.\n";
531 llvm::errs() << VirtualFileEntries.size() <<
" virtual files found, " 532 << VirtualDirectoryEntries.size() <<
" virtual dirs found.\n";
533 llvm::errs() << NumDirLookups <<
" dir lookups, " 534 << NumDirCacheMisses <<
" dir cache misses.\n";
535 llvm::errs() << NumFileLookups <<
" file lookups, " 536 << 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