From 0ab591a231517adb5befaac5d6a8f3817ca12527 Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Tue, 24 Oct 2017 01:26:22 +0000 Subject: [PATCH] [raw_fd_ostream] report actual error in error messages Summary: Previously, we would emit error messages like "IO failure on output stream". This change causes use to include information about what actually went wrong, e.g. "No space left on device". Reviewers: sunfish, rnk Reviewed By: rnk Subscribers: mehdi_amini, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D39203 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316404 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/LockFileManager.h | 2 +- include/llvm/Support/raw_ostream.h | 16 ++++++---------- lib/IR/Core.cpp | 3 ++- lib/LTO/LTOCodeGenerator.cpp | 8 +++++--- lib/Support/LockFileManager.cpp | 5 ++--- lib/Support/raw_ostream.cpp | 20 +++++++++++--------- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 13d252425b9..f14ac1cee94 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -88,7 +88,7 @@ public: std::string getErrorMessage() const; /// \brief Set error and error message - void setError(std::error_code &EC, StringRef ErrorMsg = "") { + void setError(const std::error_code &EC, StringRef ErrorMsg = "") { Error = EC; ErrorDiagMsg = ErrorMsg.str(); } diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 565833c95b7..d11f5a83779 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -362,9 +362,7 @@ class raw_fd_ostream : public raw_pwrite_stream { int FD; bool ShouldClose; - /// Error This flag is true if an error of any kind has been detected. - /// - bool Error; + std::error_code EC; uint64_t pos; @@ -383,7 +381,7 @@ class raw_fd_ostream : public raw_pwrite_stream { size_t preferred_buffer_size() const override; /// Set the flag indicating that an output error has been encountered. - void error_detected() { Error = true; } + void error_detected(std::error_code EC) { this->EC = EC; } public: /// Open the specified file for writing. If an error occurs, information @@ -424,13 +422,13 @@ public: bool has_colors() const override; + std::error_code error() const { return EC; } + /// Return the value of the flag in this raw_fd_ostream indicating whether an /// output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't /// guarantee to detect all errors unless the stream has been closed. - bool has_error() const { - return Error; - } + bool has_error() const { return bool(EC); } /// Set the flag read by has_error() to false. If the error flag is set at the /// time when this raw_ostream's destructor is called, report_fatal_error is @@ -441,9 +439,7 @@ public: /// Unless explicitly silenced." /// - from The Zen of Python, by Tim Peters /// - void clear_error() { - Error = false; - } + void clear_error() { EC = std::error_code(); } }; /// This returns a reference to a raw_ostream for standard output. Use it like: diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index abb83e01e0c..54c73b01acf 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -276,7 +276,8 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, dest.close(); if (dest.has_error()) { - *ErrorMessage = strdup("Error printing to file"); + std::string E = "Error printing to file: " + dest.error().message(); + *ErrorMessage = strdup(E.c_str()); return true; } diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 9693a7c254c..ba5c04d5b1a 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -218,7 +218,7 @@ bool LTOCodeGenerator::writeMergedModules(StringRef Path) { ToolOutputFile Out(Path, EC, sys::fs::F_None); if (EC) { std::string ErrMsg = "could not open bitcode file for writing: "; - ErrMsg += Path; + ErrMsg += Path.str() + ": " + EC.message(); emitError(ErrMsg); return false; } @@ -229,7 +229,7 @@ bool LTOCodeGenerator::writeMergedModules(StringRef Path) { if (Out.os().has_error()) { std::string ErrMsg = "could not write bitcode file: "; - ErrMsg += Path; + ErrMsg += Path.str() + ": " + Out.os().error().message(); emitError(ErrMsg); Out.os().clear_error(); return false; @@ -260,7 +260,9 @@ bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) { bool genResult = compileOptimized(&objFile.os()); objFile.os().close(); if (objFile.os().has_error()) { - emitError((Twine("could not write object file: ") + Filename).str()); + emitError((Twine("could not write object file: ") + Filename + ": " + + objFile.os().error().message()) + .str()); objFile.os().clear_error(); sys::fs::remove(Twine(Filename)); return false; diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 3ee3af7731e..81f3fd0b887 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -201,12 +201,11 @@ LockFileManager::LockFileManager(StringRef FileName) Out.close(); if (Out.has_error()) { - // We failed to write out PID, so make up an excuse, remove the + // We failed to write out PID, so report the error, remove the // unique lock file, and fail. - auto EC = make_error_code(errc::no_space_on_device); std::string S("failed to write to "); S.append(UniqueLockFileName.str()); - setError(EC, S); + setError(Out.error(), S); sys::fs::remove(UniqueLockFileName); return; } diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index c66457ca066..d6b958d1844 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -517,8 +517,7 @@ raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, /// FD is the file descriptor that this writes to. If ShouldClose is true, this /// closes the file when the stream is destroyed. raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) - : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose), - Error(false) { + : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose) { if (FD < 0 ) { ShouldClose = false; return; @@ -552,8 +551,10 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) raw_fd_ostream::~raw_fd_ostream() { if (FD >= 0) { flush(); - if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) - error_detected(); + if (ShouldClose) { + if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(EC); + } } #ifdef __MINGW32__ @@ -569,7 +570,8 @@ raw_fd_ostream::~raw_fd_ostream() { // has_error() and clear the error flag with clear_error() before // destructing raw_ostream objects which may have errors. if (has_error()) - report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false); + report_fatal_error("IO failure on output stream: " + error().message(), + /*GenCrashDiag=*/false); } void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { @@ -613,7 +615,7 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { continue; // Otherwise it's a non-recoverable error. Note it and quit. - error_detected(); + error_detected(std::error_code(errno, std::generic_category())); break; } @@ -629,8 +631,8 @@ void raw_fd_ostream::close() { assert(ShouldClose); ShouldClose = false; flush(); - if (sys::Process::SafelyCloseFileDescriptor(FD)) - error_detected(); + if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(EC); FD = -1; } @@ -645,7 +647,7 @@ uint64_t raw_fd_ostream::seek(uint64_t off) { pos = ::lseek(FD, off, SEEK_SET); #endif if (pos == (uint64_t)-1) - error_detected(); + error_detected(std::error_code(errno, std::generic_category())); return pos; } -- 2.11.0