Index: clang/include/clang/Basic/FileManager.h =================================================================== --- clang/include/clang/Basic/FileManager.h +++ clang/include/clang/Basic/FileManager.h @@ -110,26 +110,27 @@ /// 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,9 +285,17 @@ /// /// \param CacheFailure If true and the file does not exist, we'll cache /// the failure to find this file. - llvm::ErrorOr getFileRef(StringRef Filename, - bool OpenFile = false, - bool CacheFailure = true); + llvm::Expected getFileRef(StringRef Filename, + bool OpenFile = false, + bool CacheFailure = true); + + /// Get a FileEntryRef if it exists, without doing anything on error. + llvm::Optional 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; } Index: clang/lib/Basic/FileManager.cpp =================================================================== --- clang/lib/Basic/FileManager.cpp +++ clang/lib/Basic/FileManager.cpp @@ -187,10 +187,10 @@ auto Result = getFileRef(Filename, openFile, CacheFailure); if (Result) return &Result->getFileEntry(); - return Result.getError(); + return llvm::errorToErrorCode(Result.takeError()); } -llvm::ErrorOr +llvm::Expected FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { ++NumFileLookups; @@ -199,7 +199,8 @@ 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 @@ else SeenFileEntries.erase(Filename); - return DirInfoOrErr.getError(); + return llvm::errorCodeToError(DirInfoOrErr.getError()); } const DirectoryEntry *DirInfo = *DirInfoOrErr; @@ -249,7 +250,7 @@ else SeenFileEntries.erase(Filename); - return statError; + return llvm::errorCodeToError(statError); } assert((openFile || !F) && "undesired open file"); Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== --- clang/lib/Frontend/CompilerInstance.cpp +++ clang/lib/Frontend/CompilerInstance.cpp @@ -833,6 +833,8 @@ 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; } Index: clang/lib/Lex/HeaderMap.cpp =================================================================== --- clang/lib/Lex/HeaderMap.cpp +++ clang/lib/Lex/HeaderMap.cpp @@ -204,9 +204,7 @@ if (Dest.empty()) return None; - if (auto File = FM.getFileRef(Dest)) - return *File; - return None; + return FM.getOptionalFileRef(Dest); } StringRef HeaderMapImpl::lookupFilename(StringRef Filename, Index: clang/lib/Lex/HeaderSearch.cpp =================================================================== --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -314,7 +314,7 @@ 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 @@ 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 @@ FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); - llvm::ErrorOr 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 @@ 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 @@ } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - llvm::ErrorOr 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 @@ } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - File = FileMgr.getFileRef(HeadersFilename, /*OpenFile=*/true); + File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); if (!File) return None; Index: llvm/include/llvm/Support/Error.h =================================================================== --- llvm/include/llvm/Support/Error.h +++ llvm/include/llvm/Support/Error.h @@ -982,6 +982,20 @@ 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 Optional expectedToOptional(Expected &&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