[raw_fd_ostream] report actual error in error messages
authorBob Haarman <llvm@inglorion.net>
Tue, 24 Oct 2017 01:26:22 +0000 (01:26 +0000)
committerBob Haarman <llvm@inglorion.net>
Tue, 24 Oct 2017 01:26:22 +0000 (01:26 +0000)
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

llvm-svn: 316404

llvm/include/llvm/Support/LockFileManager.h
llvm/include/llvm/Support/raw_ostream.h
llvm/lib/IR/Core.cpp
llvm/lib/LTO/LTOCodeGenerator.cpp
llvm/lib/Support/LockFileManager.cpp
llvm/lib/Support/raw_ostream.cpp

index 13d2524..f14ac1c 100644 (file)
@@ -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();
   }
index 565833c..d11f5a8 100644 (file)
@@ -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:
index abb83e0..54c73b0 100644 (file)
@@ -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;
   }
 
index 9693a7c..ba5c04d 100644 (file)
@@ -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;
index 3ee3af7..81f3fd0 100644 (file)
@@ -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;
     }
index c66457c..d6b958d 100644 (file)
@@ -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;
 }