Replace clang::FileData with llvm::vfs::Status

Summary:
FileData was only ever used as a container for the values in
llvm::vfs::Status, so they might as well be consolidated.

The `InPCH` member was also always set to false, and unused.

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D58924

llvm-svn: 355368
This commit is contained in:
Harlan Haskins 2019-03-05 02:27:12 +00:00
parent 1c014d75b4
commit 06f64d53ae
6 changed files with 65 additions and 102 deletions

View File

@ -67,7 +67,6 @@ class FileEntry {
unsigned UID; // A unique (small) ID for the file.
llvm::sys::fs::UniqueID UniqueID;
bool IsNamedPipe;
bool InPCH;
bool IsValid; // Is this \c FileEntry initialized and valid?
/// The open file, if it is owned by the \p FileEntry.
@ -75,7 +74,7 @@ class FileEntry {
public:
FileEntry()
: UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
: UniqueID(0, 0), IsNamedPipe(false), IsValid(false)
{}
FileEntry(const FileEntry &) = delete;
@ -87,7 +86,6 @@ public:
off_t getSize() const { return Size; }
unsigned getUID() const { return UID; }
const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
bool isInPCH() const { return InPCH; }
time_t getModificationTime() const { return ModTime; }
/// Return the directory the file lives in.
@ -108,8 +106,6 @@ public:
bool isOpenForTests() const { return File != nullptr; }
};
struct FileData;
/// Implements support for file system lookup, file system caching,
/// and directory search management.
///
@ -168,7 +164,7 @@ class FileManager : public RefCountedBase<FileManager> {
// Caching.
std::unique_ptr<FileSystemStatCache> StatCache;
bool getStatValue(StringRef Path, FileData &Data, bool isFile,
bool getStatValue(StringRef Path, llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F);
/// Add all ancestors of the given path (pointing to either a file

View File

@ -19,40 +19,15 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <cstdint>
#include <ctime>
#include <memory>
#include <string>
#include <utility>
namespace llvm {
namespace vfs {
class File;
class FileSystem;
} // namespace vfs
} // namespace llvm
namespace clang {
// FIXME: should probably replace this with vfs::Status
struct FileData {
std::string Name;
uint64_t Size = 0;
time_t ModTime = 0;
llvm::sys::fs::UniqueID UniqueID;
bool IsDirectory = false;
bool IsNamedPipe = false;
bool InPCH = false;
// FIXME: remove this when files support multiple names
bool IsVFSMapped = false;
FileData() = default;
};
/// Abstract interface for introducing a FileManager cache for 'stat'
/// system calls, which is used by precompiled and pretokenized headers to
/// improve performance.
@ -80,7 +55,7 @@ public:
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in \p F with a valid \p File object and
/// the client guarantees that it will close it.
static bool get(StringRef Path, FileData &Data, bool isFile,
static bool get(StringRef Path, llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS);
@ -88,7 +63,8 @@ protected:
// FIXME: The pointer here is a non-owning/optional reference to the
// unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
// Optional needs some work to support references so this isn't possible yet.
virtual LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
virtual LookupResult getStat(StringRef Path, llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
llvm::vfs::FileSystem &FS) = 0;
};
@ -99,15 +75,16 @@ protected:
class MemorizeStatCalls : public FileSystemStatCache {
public:
/// The set of stat() calls that have been seen.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
llvm::StringMap<llvm::vfs::Status, llvm::BumpPtrAllocator> StatCalls;
using iterator =
llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator;
llvm::StringMap<llvm::vfs::Status,
llvm::BumpPtrAllocator>::const_iterator;
iterator begin() const { return StatCalls.begin(); }
iterator end() const { return StatCalls.end(); }
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
LookupResult getStat(StringRef Path, llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
llvm::vfs::FileSystem &FS) override;
};

View File

@ -144,8 +144,8 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
StringRef InterndDirName = NamedDirEnt.first();
// Check to see if the directory exists.
FileData Data;
if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) {
llvm::vfs::Status Status;
if (getStatValue(InterndDirName, Status, false, nullptr /*directory lookup*/)) {
// There's no real directory at the given path.
if (!CacheFailure)
SeenDirEntries.erase(DirName);
@ -156,7 +156,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
// same inode (this occurs on Unix-like systems when one dir is
// symlinked to another, for example) or the same path (on
// Windows).
DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
DirectoryEntry &UDE = UniqueRealDirs[Status.getUniqueID()];
NamedDirEnt.second = &UDE;
if (UDE.getName().empty()) {
@ -205,8 +205,8 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// Check to see if the file exists.
std::unique_ptr<llvm::vfs::File> F;
FileData Data;
if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
llvm::vfs::Status Status;
if (getStatValue(InterndFileName, Status, true, openFile ? &F : nullptr)) {
// There's no real file at the given path.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
@ -218,14 +218,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()];
NamedFileEnt.second = &UFE;
// If the name returned by getStatValue is different than Filename, re-intern
// the name.
if (Data.Name != Filename) {
auto &NamedFileEnt = *SeenFileEntries.insert({Data.Name, &UFE}).first;
if (Status.getName() != Filename) {
auto &NamedFileEnt =
*SeenFileEntries.insert({Status.getName(), &UFE}).first;
assert(NamedFileEnt.second == &UFE &&
"filename from getStatValue() refers to wrong file");
InterndFileName = NamedFileEnt.first().data();
@ -239,7 +240,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// module's structure when its headers/module map are mapped in the VFS.
// We should remove this as soon as we can properly support a file having
// multiple names.
if (DirInfo != UFE.Dir && Data.IsVFSMapped)
if (DirInfo != UFE.Dir && Status.IsVFSMapped)
UFE.Dir = DirInfo;
// Always update the name to use the last name by which a file was accessed.
@ -254,13 +255,12 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// Otherwise, we don't have this file yet, add it.
UFE.Name = InterndFileName;
UFE.Size = Data.Size;
UFE.ModTime = Data.ModTime;
UFE.Size = Status.getSize();
UFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
UFE.Dir = DirInfo;
UFE.UID = NextFileUID++;
UFE.UniqueID = Data.UniqueID;
UFE.IsNamedPipe = Data.IsNamedPipe;
UFE.InPCH = Data.InPCH;
UFE.UniqueID = Status.getUniqueID();
UFE.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
UFE.File = std::move(F);
UFE.IsValid = true;
@ -298,12 +298,15 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
"The directory of a virtual file should already be in the cache.");
// Check to see if the file exists. If so, drop the virtual file
FileData Data;
llvm::vfs::Status Status;
const char *InterndFileName = NamedFileEnt.first().data();
if (getStatValue(InterndFileName, Data, true, nullptr) == 0) {
Data.Size = Size;
Data.ModTime = ModificationTime;
UFE = &UniqueRealFiles[Data.UniqueID];
if (getStatValue(InterndFileName, Status, true, nullptr) == 0) {
UFE = &UniqueRealFiles[Status.getUniqueID()];
Status = llvm::vfs::Status(
Status.getName(), Status.getUniqueID(),
llvm::sys::toTimePoint(ModificationTime),
Status.getUser(), Status.getGroup(), Size,
Status.getType(), Status.getPermissions());
NamedFileEnt.second = UFE;
@ -317,10 +320,9 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
if (UFE->isValid())
return UFE;
UFE->UniqueID = Data.UniqueID;
UFE->IsNamedPipe = Data.IsNamedPipe;
UFE->InPCH = Data.InPCH;
fillRealPathName(UFE, Data.Name);
UFE->UniqueID = Status.getUniqueID();
UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
fillRealPathName(UFE, Status.getName());
} else {
VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
UFE = VirtualFileEntries.back().get();
@ -421,17 +423,18 @@ FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
/// if the path points to a virtual file or does not exist, or returns
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
bool FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
if (FileSystemOpts.WorkingDir.empty())
return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS);
return FileSystemStatCache::get(Path, Status, isFile, F,StatCache.get(), *FS);
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F,
return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F,
StatCache.get(), *FS);
}

View File

@ -21,18 +21,6 @@ using namespace clang;
void FileSystemStatCache::anchor() {}
static void copyStatusToFileData(const llvm::vfs::Status &Status,
FileData &Data) {
Data.Name = Status.getName();
Data.Size = Status.getSize();
Data.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
Data.UniqueID = Status.getUniqueID();
Data.IsDirectory = Status.isDirectory();
Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
Data.InPCH = false;
Data.IsVFSMapped = Status.IsVFSMapped;
}
/// FileSystemStatCache::get - Get the 'stat' information for the specified
/// path, using the cache to accelerate it if possible. This returns true if
/// the path does not exist or false if it exists.
@ -42,7 +30,8 @@ static void copyStatusToFileData(const llvm::vfs::Status &Status,
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
bool FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache,
llvm::vfs::FileSystem &FS) {
@ -51,16 +40,16 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
// If we have a cache, use it to resolve the stat query.
if (Cache)
R = Cache->getStat(Path, Data, isFile, F, FS);
R = Cache->getStat(Path, Status, isFile, F, FS);
else if (isForDir || !F) {
// If this is a directory or a file descriptor is not needed and we have
// no cache, just go to the file system.
llvm::ErrorOr<llvm::vfs::Status> Status = FS.status(Path);
if (!Status) {
llvm::ErrorOr<llvm::vfs::Status> StatusOrErr = FS.status(Path);
if (!StatusOrErr) {
R = CacheMissing;
} else {
R = CacheExists;
copyStatusToFileData(*Status, Data);
Status = *StatusOrErr;
}
} else {
// Otherwise, we have to go to the filesystem. We can always just use
@ -79,10 +68,10 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
// Otherwise, the open succeeded. Do an fstat to get the information
// about the file. We'll end up returning the open file descriptor to the
// client to do what they please with it.
llvm::ErrorOr<llvm::vfs::Status> Status = (*OwnedFile)->status();
if (Status) {
llvm::ErrorOr<llvm::vfs::Status> StatusOrErr = (*OwnedFile)->status();
if (StatusOrErr) {
R = CacheExists;
copyStatusToFileData(*Status, Data);
Status = *StatusOrErr;
*F = std::move(*OwnedFile);
} else {
// fstat rarely fails. If it does, claim the initial open didn't
@ -98,7 +87,7 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
// If the path exists, make sure that its "directoryness" matches the clients
// demands.
if (Data.IsDirectory != isForDir) {
if (Status.isDirectory() != isForDir) {
// If not, close the file if opened.
if (F)
*F = nullptr;
@ -110,10 +99,11 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
}
MemorizeStatCalls::LookupResult
MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
MemorizeStatCalls::getStat(StringRef Path, llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
llvm::vfs::FileSystem &FS) {
if (get(Path, Data, isFile, F, nullptr, FS)) {
if (get(Path, Status, isFile, F, nullptr, FS)) {
// Do not cache failed stats, it is easy to construct common inconsistent
// situations if we do, and they are not important for PCH performance
// (which currently only needs the stats to construct the initial
@ -122,8 +112,8 @@ MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
}
// Cache file 'stat' results and directories with absolutely paths.
if (!Data.IsDirectory || llvm::sys::path::is_absolute(Path))
StatCalls[Path] = Data;
if (!Status.isDirectory() || llvm::sys::path::is_absolute(Path))
StatCalls[Path] = Status;
return CacheExists;
}

View File

@ -792,8 +792,6 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
const FileEntry *FE = Loc.getFileEntry();
if (FE && FE->isValid()) {
emitFilename(FE->getName(), Loc.getManager());
if (FE->isInPCH())
OS << " (in PCH)";
OS << ": ";
}
}

View File

@ -26,7 +26,7 @@ class FakeStatCache : public FileSystemStatCache {
private:
// Maps a file/directory path to its desired stat result. Anything
// not in this map is considered to not exist in the file system.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
llvm::StringMap<llvm::vfs::Status, llvm::BumpPtrAllocator> StatCalls;
void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
#ifndef _WIN32
@ -35,15 +35,14 @@ private:
Path = NormalizedPath.c_str();
#endif
FileData Data;
Data.Name = Path;
Data.Size = 0;
Data.ModTime = 0;
Data.UniqueID = llvm::sys::fs::UniqueID(1, INode);
Data.IsDirectory = !IsFile;
Data.IsNamedPipe = false;
Data.InPCH = false;
StatCalls[Path] = Data;
auto fileType = IsFile ?
llvm::sys::fs::file_type::regular_file :
llvm::sys::fs::file_type::directory_file;
llvm::vfs::Status Status(Path, llvm::sys::fs::UniqueID(1, INode),
/*MTime*/{}, /*User*/0, /*Group*/0,
/*Size*/0, fileType,
llvm::sys::fs::perms::all_all);
StatCalls[Path] = Status;
}
public:
@ -58,7 +57,7 @@ public:
}
// Implement FileSystemStatCache::getStat().
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
LookupResult getStat(StringRef Path, llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
llvm::vfs::FileSystem &FS) override {
#ifndef _WIN32
@ -68,7 +67,7 @@ public:
#endif
if (StatCalls.count(Path) != 0) {
Data = StatCalls[Path];
Status = StatCalls[Path];
return CacheExists;
}