forked from OSchip/llvm-project
FileManager: Use llvm::Expected in new getFileRef API
`FileManager::getFileRef` is a modern API which we expect to convert to over time. We should modernize the error handling as well, using `llvm::Expected` instead of `llvm::ErrorOr`, to help clients that care about errors to ensure nothing is missed. However, not all clients care. I've also added another path for those that don't: - `FileEntryRef` is now copy- and move-assignable (using a pointer instead of a reference). - `FileManager::getOptionalFileRef` returns an `llvm::Optional` instead of `llvm::Expected`. - Added an `llvm::expectedToOptional` utility in case this is useful elsewhere. https://reviews.llvm.org/D66705 llvm-svn: 369943
This commit is contained in:
parent
36d1588f01
commit
9ef6c49baf
|
@ -110,26 +110,27 @@ public:
|
|||
/// accessed by the FileManager's client.
|
||||
class FileEntryRef {
|
||||
public:
|
||||
FileEntryRef() = delete;
|
||||
FileEntryRef(StringRef Name, const FileEntry &Entry)
|
||||
: Name(Name), Entry(Entry) {}
|
||||
: Name(Name), Entry(&Entry) {}
|
||||
|
||||
const StringRef getName() const { return Name; }
|
||||
|
||||
const FileEntry &getFileEntry() const { return Entry; }
|
||||
const FileEntry &getFileEntry() const { return *Entry; }
|
||||
|
||||
off_t getSize() const { return Entry.getSize(); }
|
||||
off_t getSize() const { return Entry->getSize(); }
|
||||
|
||||
unsigned getUID() const { return Entry.getUID(); }
|
||||
unsigned getUID() const { return Entry->getUID(); }
|
||||
|
||||
const llvm::sys::fs::UniqueID &getUniqueID() const {
|
||||
return Entry.getUniqueID();
|
||||
return Entry->getUniqueID();
|
||||
}
|
||||
|
||||
time_t getModificationTime() const { return Entry.getModificationTime(); }
|
||||
time_t getModificationTime() const { return Entry->getModificationTime(); }
|
||||
|
||||
private:
|
||||
StringRef Name;
|
||||
const FileEntry &Entry;
|
||||
const FileEntry *Entry;
|
||||
};
|
||||
|
||||
/// Implements support for file system lookup, file system caching,
|
||||
|
@ -284,10 +285,18 @@ public:
|
|||
///
|
||||
/// \param CacheFailure If true and the file does not exist, we'll cache
|
||||
/// the failure to find this file.
|
||||
llvm::ErrorOr<FileEntryRef> getFileRef(StringRef Filename,
|
||||
llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
|
||||
bool OpenFile = false,
|
||||
bool CacheFailure = true);
|
||||
|
||||
/// Get a FileEntryRef if it exists, without doing anything on error.
|
||||
llvm::Optional<FileEntryRef> getOptionalFileRef(StringRef Filename,
|
||||
bool OpenFile = false,
|
||||
bool CacheFailure = true) {
|
||||
return llvm::expectedToOptional(
|
||||
getFileRef(Filename, OpenFile, CacheFailure));
|
||||
}
|
||||
|
||||
/// Returns the current file system options
|
||||
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
|
||||
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
|
||||
|
|
|
@ -187,10 +187,10 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
|
|||
auto Result = getFileRef(Filename, openFile, CacheFailure);
|
||||
if (Result)
|
||||
return &Result->getFileEntry();
|
||||
return Result.getError();
|
||||
return llvm::errorToErrorCode(Result.takeError());
|
||||
}
|
||||
|
||||
llvm::ErrorOr<FileEntryRef>
|
||||
llvm::Expected<FileEntryRef>
|
||||
FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
||||
++NumFileLookups;
|
||||
|
||||
|
@ -199,7 +199,8 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
|||
SeenFileEntries.insert({Filename, std::errc::no_such_file_or_directory});
|
||||
if (!SeenFileInsertResult.second) {
|
||||
if (!SeenFileInsertResult.first->second)
|
||||
return SeenFileInsertResult.first->second.getError();
|
||||
return llvm::errorCodeToError(
|
||||
SeenFileInsertResult.first->second.getError());
|
||||
// Construct and return and FileEntryRef, unless it's a redirect to another
|
||||
// filename.
|
||||
SeenFileEntryOrRedirect Value = *SeenFileInsertResult.first->second;
|
||||
|
@ -230,7 +231,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
|||
else
|
||||
SeenFileEntries.erase(Filename);
|
||||
|
||||
return DirInfoOrErr.getError();
|
||||
return llvm::errorCodeToError(DirInfoOrErr.getError());
|
||||
}
|
||||
const DirectoryEntry *DirInfo = *DirInfoOrErr;
|
||||
|
||||
|
@ -249,7 +250,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
|
|||
else
|
||||
SeenFileEntries.erase(Filename);
|
||||
|
||||
return statError;
|
||||
return llvm::errorCodeToError(statError);
|
||||
}
|
||||
|
||||
assert((openFile || !F) && "undesired open file");
|
||||
|
|
|
@ -833,6 +833,8 @@ bool CompilerInstance::InitializeSourceManager(
|
|||
if (InputFile != "-") {
|
||||
auto FileOrErr = FileMgr.getFileRef(InputFile, /*OpenFile=*/true);
|
||||
if (!FileOrErr) {
|
||||
// FIXME: include the error in the diagnostic.
|
||||
consumeError(FileOrErr.takeError());
|
||||
Diags.Report(diag::err_fe_error_reading) << InputFile;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -204,9 +204,7 @@ Optional<FileEntryRef> HeaderMap::LookupFile(StringRef Filename,
|
|||
if (Dest.empty())
|
||||
return None;
|
||||
|
||||
if (auto File = FM.getFileRef(Dest))
|
||||
return *File;
|
||||
return None;
|
||||
return FM.getOptionalFileRef(Dest);
|
||||
}
|
||||
|
||||
StringRef HeaderMapImpl::lookupFilename(StringRef Filename,
|
||||
|
|
|
@ -314,7 +314,7 @@ Optional<FileEntryRef> HeaderSearch::getFileAndSuggestModule(
|
|||
if (!File) {
|
||||
// For rare, surprising errors (e.g. "out of file handles"), diag the EC
|
||||
// message.
|
||||
std::error_code EC = File.getError();
|
||||
std::error_code EC = llvm::errorToErrorCode(File.takeError());
|
||||
if (EC != llvm::errc::no_such_file_or_directory &&
|
||||
EC != llvm::errc::invalid_argument &&
|
||||
EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
|
||||
|
@ -401,7 +401,7 @@ Optional<FileEntryRef> DirectoryLookup::LookupFile(
|
|||
FixupSearchPath();
|
||||
return *Result;
|
||||
}
|
||||
} else if (auto Res = HS.getFileMgr().getFileRef(Dest)) {
|
||||
} else if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest)) {
|
||||
FixupSearchPath();
|
||||
return *Res;
|
||||
}
|
||||
|
@ -553,9 +553,8 @@ Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup(
|
|||
|
||||
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
|
||||
|
||||
llvm::ErrorOr<FileEntryRef> File =
|
||||
FileMgr.getFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);
|
||||
|
||||
auto File =
|
||||
FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);
|
||||
if (!File) {
|
||||
// Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
|
||||
const char *Private = "Private";
|
||||
|
@ -565,7 +564,8 @@ Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup(
|
|||
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
|
||||
Private+strlen(Private));
|
||||
|
||||
File = FileMgr.getFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);
|
||||
File = FileMgr.getOptionalFileRef(FrameworkName,
|
||||
/*OpenFile=*/!SuggestedModule);
|
||||
}
|
||||
|
||||
// If we found the header and are allowed to suggest a module, do so now.
|
||||
|
@ -1076,9 +1076,7 @@ Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader(
|
|||
}
|
||||
|
||||
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
|
||||
llvm::ErrorOr<FileEntryRef> File =
|
||||
FileMgr.getFileRef(HeadersFilename, /*OpenFile=*/true);
|
||||
|
||||
auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);
|
||||
if (!File) {
|
||||
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
|
||||
HeadersFilename = FrameworkName;
|
||||
|
@ -1090,7 +1088,7 @@ Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader(
|
|||
}
|
||||
|
||||
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
|
||||
File = FileMgr.getFileRef(HeadersFilename, /*OpenFile=*/true);
|
||||
File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);
|
||||
|
||||
if (!File)
|
||||
return None;
|
||||
|
|
|
@ -982,6 +982,20 @@ inline void consumeError(Error Err) {
|
|||
handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
|
||||
}
|
||||
|
||||
/// Convert an Expected to an Optional without doing anything. This method
|
||||
/// should be used only where an error can be considered a reasonable and
|
||||
/// expected return value.
|
||||
///
|
||||
/// Uses of this method are potentially indicative of problems: perhaps the
|
||||
/// error should be propagated further, or the error-producer should just
|
||||
/// return an Optional in the first place.
|
||||
template <typename T> Optional<T> expectedToOptional(Expected<T> &&E) {
|
||||
if (E)
|
||||
return std::move(*E);
|
||||
consumeError(E.takeError());
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Helper for converting an Error to a bool.
|
||||
///
|
||||
/// This method returns true if Err is in an error state, or false if it is
|
||||
|
|
Loading…
Reference in New Issue