summaryrefslogtreecommitdiffstats
path: root/lib/Basic/FileManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/FileManager.cpp')
-rw-r--r--lib/Basic/FileManager.cpp61
1 files changed, 47 insertions, 14 deletions
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index fd6d334..c6b894c 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -111,6 +111,14 @@ public:
}
size_t size() const { return UniqueFiles.size(); }
+
+ void erase(const FileEntry *Entry) {
+ std::string FullPath(GetFullPath(Entry->getName()));
+
+ // Lowercase string because Windows filesystem is case insensitive.
+ FullPath = StringRef(FullPath).lower();
+ UniqueFiles.erase(FullPath);
+ }
};
//===----------------------------------------------------------------------===//
@@ -152,6 +160,8 @@ public:
}
size_t size() const { return UniqueFiles.size(); }
+
+ void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); }
};
#endif
@@ -213,6 +223,10 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) {
PrevCache->setNextStatCache(statCache->getNextStatCache());
}
+void FileManager::clearStatCaches() {
+ StatCache.reset(0);
+}
+
/// \brief Retrieve the directory that the given file name resides in.
/// Filename can point to either a real file or a virtual file.
static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
@@ -259,16 +273,14 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
addAncestorsAsVirtualDirs(DirName);
}
-/// getDirectory - Lookup, cache, and verify the specified directory
-/// (real or virtual). This returns NULL if the directory doesn't
-/// exist.
-///
const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
bool CacheFailure) {
- // stat doesn't like trailing separators.
+ // stat doesn't like trailing separators except for root directory.
// At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
// (though it can strip '\\')
- if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back()))
+ if (DirName.size() > 1 &&
+ DirName != llvm::sys::path::root_path(DirName) &&
+ llvm::sys::path::is_separator(DirName.back()))
DirName = DirName.substr(0, DirName.size()-1);
++NumDirLookups;
@@ -315,9 +327,6 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
return &UDE;
}
-/// getFile - Lookup, cache, and verify the specified file (real or
-/// virtual). This returns NULL if the file doesn't exist.
-///
const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
bool CacheFailure) {
++NumFileLookups;
@@ -483,15 +492,21 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
}
llvm::MemoryBuffer *FileManager::
-getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
+getBufferForFile(const FileEntry *Entry, std::string *ErrorStr,
+ bool isVolatile) {
OwningPtr<llvm::MemoryBuffer> Result;
llvm::error_code ec;
+ uint64_t FileSize = Entry->getSize();
+ // If there's a high enough chance that the file have changed since we
+ // got its size, force a stat before opening it.
+ if (isVolatile)
+ FileSize = -1;
+
const char *Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
if (Entry->FD != -1) {
- ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
- Entry->getSize());
+ ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize);
if (ErrorStr)
*ErrorStr = ec.message();
@@ -503,7 +518,7 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
// Otherwise, open the file.
if (FileSystemOpts.WorkingDir.empty()) {
- ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize());
+ ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize);
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.take();
@@ -511,7 +526,7 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
SmallString<128> FilePath(Entry->getName());
FixupRelativePath(FilePath);
- ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize());
+ ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize);
if (ec && ErrorStr)
*ErrorStr = ec.message();
return Result.take();
@@ -564,6 +579,18 @@ bool FileManager::getNoncachedStatValue(StringRef Path,
return ::stat(FilePath.c_str(), &StatBuf) != 0;
}
+void FileManager::invalidateCache(const FileEntry *Entry) {
+ assert(Entry && "Cannot invalidate a NULL FileEntry");
+
+ SeenFileEntries.erase(Entry->getName());
+
+ // FileEntry invalidation should not block future optimizations in the file
+ // caches. Possible alternatives are cache truncation (invalidate last N) or
+ // invalidation of the whole cache.
+ UniqueRealFiles.erase(Entry);
+}
+
+
void FileManager::GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
@@ -584,6 +611,12 @@ void FileManager::GetUniqueIDMapping(
UIDToFiles[(*VFE)->getUID()] = *VFE;
}
+void FileManager::modifyFileEntry(FileEntry *File,
+ off_t Size, time_t ModificationTime) {
+ File->Size = Size;
+ File->ModTime = ModificationTime;
+}
+
void FileManager::PrintStats() const {
llvm::errs() << "\n*** File Manager Stats:\n";
OpenPOWER on IntegriCloud