jfb updated this revision to Diff 213497.
jfb marked 8 inline comments as done.
jfb added a comment.

- Return llvm::Error from ASTUnit::Save
- Update per comments.
- Address Volodymyr's comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65545/new/

https://reviews.llvm.org/D65545

Files:
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/include/clang/Frontend/ASTUnit.h
  clang/include/clang/Frontend/PrecompiledPreamble.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Frontend/DependencyFile.cpp
  clang/lib/Frontend/PrecompiledPreamble.cpp
  clang/lib/Rewrite/Rewriter.cpp
  clang/lib/Serialization/GlobalModuleIndex.cpp
  clang/tools/driver/cc1gen_reproducer_main.cpp
  clang/tools/libclang/CIndex.cpp
  clang/unittests/CrossTU/CrossTranslationUnitTest.cpp
  clang/unittests/Frontend/ASTUnitTest.cpp
  llvm/include/llvm/Support/FileUtilities.h
  llvm/lib/Support/GraphWriter.cpp
  llvm/lib/Support/LockFileManager.cpp
  llvm/lib/Support/Path.cpp
  llvm/lib/Support/ToolOutputFile.cpp

Index: llvm/lib/Support/ToolOutputFile.cpp
===================================================================
--- llvm/lib/Support/ToolOutputFile.cpp
+++ llvm/lib/Support/ToolOutputFile.cpp
@@ -25,7 +25,9 @@
 ToolOutputFile::CleanupInstaller::~CleanupInstaller() {
   // Delete the file if the client hasn't told us not to.
   if (!Keep && Filename != "-")
-    sys::fs::remove(Filename);
+    if (std::error_code EC = sys::fs::remove(Filename))
+      report_fatal_error("Failed removing file \"" + Filename +
+                         "\": " + EC.message());
 
   // Ok, the file is successfully written and closed, or deleted. There's no
   // further need to clean it up on signals.
Index: llvm/lib/Support/Path.cpp
===================================================================
--- llvm/lib/Support/Path.cpp
+++ llvm/lib/Support/Path.cpp
@@ -1182,9 +1182,10 @@
   if (RenameEC) {
     // If we can't rename, try to copy to work around cross-device link issues.
     RenameEC = sys::fs::copy_file(TmpName, Name);
-    // If we can't rename or copy, discard the temporary file.
+    // If we can't rename or copy, discard the temporary file, ignoring any
+    // further failure.
     if (RenameEC)
-      remove(TmpName);
+      (void)remove(TmpName);
   }
   sys::DontRemoveFileOnSignal(TmpName);
 #endif
Index: llvm/lib/Support/LockFileManager.cpp
===================================================================
--- llvm/lib/Support/LockFileManager.cpp
+++ llvm/lib/Support/LockFileManager.cpp
@@ -47,14 +47,16 @@
 /// \param LockFileName The name of the lock file to read.
 ///
 /// \returns The process ID of the process that owns this lock file
-Optional<std::pair<std::string, int> >
+Optional<std::pair<std::string, int>>
 LockFileManager::readLockFile(StringRef LockFileName) {
   // Read the owning host and PID out of the lock file. If it appears that the
   // owning process is dead, the lock file is invalid.
   ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
       MemoryBuffer::getFile(LockFileName);
   if (!MBOrErr) {
-    sys::fs::remove(LockFileName);
+    if (std::error_code EC = sys::fs::remove(LockFileName))
+      report_fatal_error("Unable to remove invalid lock file \"" +
+                         LockFileName + "\": " + EC.message());
     return None;
   }
   MemoryBuffer &MB = *MBOrErr.get();
@@ -71,7 +73,9 @@
   }
 
   // Delete the lock file. It's invalid anyway.
-  sys::fs::remove(LockFileName);
+  if (std::error_code EC = sys::fs::remove(LockFileName))
+    report_fatal_error("Unable to remove invalid lock file \"" + LockFileName +
+                       "\": " + EC.message());
   return None;
 }
 
@@ -144,7 +148,9 @@
       // released.
       return;
     }
-    sys::fs::remove(Filename);
+    if (std::error_code EC = sys::fs::remove(Filename))
+      report_fatal_error("Unable to remove unique lock file on signal \"" +
+                         Filename + "\": " + EC.message());
     sys::DontRemoveFileOnSignal(Filename);
   }
 
@@ -204,8 +210,9 @@
       // unique lock file, and fail.
       std::string S("failed to write to ");
       S.append(UniqueLockFileName.str());
+      if (std::error_code EC = sys::fs::remove(UniqueLockFileName))
+        S.append(", also failed to remove the lockfile");
       setError(Out.error(), S);
-      sys::fs::remove(UniqueLockFileName);
       return;
     }
   }
@@ -234,8 +241,12 @@
     // Someone else managed to create the lock file first. Read the process ID
     // from the lock file.
     if ((Owner = readLockFile(LockFileName))) {
-      // Wipe out our unique lock file (it's useless now)
-      sys::fs::remove(UniqueLockFileName);
+      // Wipe out our unique lock file (it's useless now).
+      if ((EC = sys::fs::remove(UniqueLockFileName))) {
+        std::string S("failed to remove useless lockfile ");
+        S.append(UniqueLockFileName.str());
+        setError(EC, S);
+      }
       return;
     }
 
@@ -283,8 +294,12 @@
     return;
 
   // Since we own the lock, remove the lock file and our own unique lock file.
-  sys::fs::remove(LockFileName);
-  sys::fs::remove(UniqueLockFileName);
+  if (std::error_code EC = sys::fs::remove(LockFileName))
+    report_fatal_error("failed removing file \"" + LockFileName +
+                       "\": " + EC.message());
+  if (std::error_code EC = sys::fs::remove(UniqueLockFileName))
+    report_fatal_error("failed removing file \"" + UniqueLockFileName +
+                       "\": " + EC.message());
   // The unique file is now gone, so remove it from the signal handler. This
   // matches a sys::RemoveFileOnSignal() in LockFileManager().
   sys::DontRemoveFileOnSignal(UniqueLockFileName);
Index: llvm/lib/Support/GraphWriter.cpp
===================================================================
--- llvm/lib/Support/GraphWriter.cpp
+++ llvm/lib/Support/GraphWriter.cpp
@@ -98,7 +98,9 @@
       errs() << "Error: " << ErrMsg << "\n";
       return true;
     }
-    sys::fs::remove(Filename);
+    if (std::error_code EC = sys::fs::remove(Filename))
+      errs() << "Failed removing file \"" << Filename << "\": " << EC.message()
+             << '\n';
     errs() << " done. \n";
   } else {
     sys::ExecuteNoWait(ExecPath, args, None, {}, 0, &ErrMsg);
Index: llvm/include/llvm/Support/FileUtilities.h
===================================================================
--- llvm/include/llvm/Support/FileUtilities.h
+++ llvm/include/llvm/Support/FileUtilities.h
@@ -49,8 +49,9 @@
 
     ~FileRemover() {
       if (DeleteIt) {
-        // Ignore problems deleting the file.
-        sys::fs::remove(Filename);
+        if (std::error_code EC = sys::fs::remove(Filename))
+          report_fatal_error("failed removing file \"" + Filename +
+                             "\": " + EC.message());
       }
     }
 
@@ -59,8 +60,9 @@
     /// had ownership of a file, remove it first.
     void setFile(const Twine& filename, bool deleteIt = true) {
       if (DeleteIt) {
-        // Ignore problems deleting the file.
-        sys::fs::remove(Filename);
+        if (std::error_code EC = sys::fs::remove(Filename))
+          report_fatal_error("failed removing file \"" + Filename +
+                             "\": " + EC.message());
       }
 
       Filename.clear();
Index: clang/unittests/Frontend/ASTUnitTest.cpp
===================================================================
--- clang/unittests/Frontend/ASTUnitTest.cpp
+++ clang/unittests/Frontend/ASTUnitTest.cpp
@@ -82,7 +82,8 @@
   ASSERT_FALSE(
       llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
   ToolOutputFile ast_file(ASTFileName, FD);
-  AST->Save(ASTFileName.str());
+  llvm::Error E = AST->Save(ASTFileName.str());
+  EXPECT_FALSE(E);
 
   EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
 
Index: clang/unittests/CrossTU/CrossTranslationUnitTest.cpp
===================================================================
--- clang/unittests/CrossTU/CrossTranslationUnitTest.cpp
+++ clang/unittests/CrossTU/CrossTranslationUnitTest.cpp
@@ -72,7 +72,8 @@
 
     std::unique_ptr<ASTUnit> ASTWithDefinition =
         tooling::buildASTFromCode(SourceText, SourceFileName);
-    ASTWithDefinition->Save(ASTFileName.str());
+    llvm::Error E = ASTWithDefinition->Save(ASTFileName.str());
+    EXPECT_FALSE(E);
     EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
 
     // Load the definition from the AST file.
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -3978,8 +3978,10 @@
   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
     setThreadBackgroundPriority();
 
-  bool hadError = cxtu::getASTUnit(TU)->Save(FileName);
-  return hadError ? CXSaveError_Unknown : CXSaveError_None;
+  llvm::Error E = cxtu::getASTUnit(TU)->Save(FileName);
+  CXSaveError Res = E ? CXSaveError_Unknown : CXSaveError_None;
+  consumeError(std::move(E));
+  return Res;
 }
 
 int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
Index: clang/tools/driver/cc1gen_reproducer_main.cpp
===================================================================
--- clang/tools/driver/cc1gen_reproducer_main.cpp
+++ clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -190,6 +190,11 @@
   }
 
   // Remove the input file.
-  llvm::sys::fs::remove(Input);
+  if (std::error_code EC = llvm::sys::fs::remove(Input)) {
+    llvm::errs() << "error: failed to remove file " << Input << ": "
+                 << EC.message() << "\n";
+    return 1;
+  }
+
   return Result;
 }
Index: clang/lib/Serialization/GlobalModuleIndex.cpp
===================================================================
--- clang/lib/Serialization/GlobalModuleIndex.cpp
+++ clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -932,12 +932,14 @@
     return llvm::createStringError(Out.error(), "failed writing to stream");
 
   // Remove the old index file. It isn't relevant any more.
-  llvm::sys::fs::remove(IndexPath);
+  if (std::error_code EC = llvm::sys::fs::remove(IndexPath))
+    return llvm::createStringError(EC, "failed removing \"%s\"",
+                                   IndexPath.c_str());
 
   // Rename the newly-written index file to the proper name.
   if (std::error_code Err = llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
     // Remove the file on failure, don't check whether removal succeeded.
-    llvm::sys::fs::remove(IndexTmpPath);
+    (void)llvm::sys::fs::remove(IndexTmpPath);
     return llvm::createStringError(Err, "failed renaming file \"%s\" to \"%s\"",
                                    IndexTmpPath.c_str(), IndexPath.c_str());
   }
Index: clang/lib/Rewrite/Rewriter.cpp
===================================================================
--- clang/lib/Rewrite/Rewriter.cpp
+++ clang/lib/Rewrite/Rewriter.cpp
@@ -434,7 +434,7 @@
         << TempFilename << Filename << ec.message();
       // If the remove fails, there's not a lot we can do - this is already an
       // error.
-      llvm::sys::fs::remove(TempFilename);
+      (void)llvm::sys::fs::remove(TempFilename);
     }
   }
 
Index: clang/lib/Frontend/PrecompiledPreamble.cpp
===================================================================
--- clang/lib/Frontend/PrecompiledPreamble.cpp
+++ clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -26,6 +26,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Mutex.h"
 #include "llvm/Support/MutexGuard.h"
@@ -34,6 +35,8 @@
 #include <limits>
 #include <utility>
 
+#define DEBUG_TYPE "pch"
+
 using namespace clang;
 
 namespace {
@@ -93,7 +96,7 @@
   void addFile(StringRef File);
 
   /// Remove \p File from disk and from the set of tracked files.
-  void removeFile(StringRef File);
+  llvm::Error removeFile(StringRef File);
 
 private:
   llvm::sys::SmartMutex<false> Mutex;
@@ -108,7 +111,10 @@
 TemporaryFiles::~TemporaryFiles() {
   llvm::MutexGuard Guard(Mutex);
   for (const auto &File : Files)
-    llvm::sys::fs::remove(File.getKey());
+    if (std::error_code EC = llvm::sys::fs::remove(File.getKey())) {
+      LLVM_DEBUG(llvm::dbgs() << "failed removing file \"" << File.getKey() <<
+                               "\": " << EC.message());
+    }
 }
 
 void TemporaryFiles::addFile(StringRef File) {
@@ -118,12 +124,14 @@
   assert(IsInserted && "File has already been added");
 }
 
-void TemporaryFiles::removeFile(StringRef File) {
+llvm::Error TemporaryFiles::removeFile(StringRef File) {
   llvm::MutexGuard Guard(Mutex);
   auto WasPresent = Files.erase(File);
   (void)WasPresent;
   assert(WasPresent && "File was not tracked");
-  llvm::sys::fs::remove(File);
+  if (std::error_code EC = llvm::sys::fs::remove(File))
+    return llvm::createStringError(EC, "failed removing \"" + File + "\"");
+  return llvm::Error::success();
 }
 
 class PrecompilePreambleAction : public ASTFrontendAction {
@@ -575,20 +583,28 @@
 
 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::TempPCHFile::
 operator=(TempPCHFile &&Other) {
-  RemoveFileIfPresent();
+  if (llvm::Error E = RemoveFileIfPresent())
+    llvm::report_fatal_error("failed assigning temporary PCH file: " +
+                             toString(std::move(E)));
 
   FilePath = std::move(Other.FilePath);
   Other.FilePath = None;
   return *this;
 }
 
-PrecompiledPreamble::TempPCHFile::~TempPCHFile() { RemoveFileIfPresent(); }
+PrecompiledPreamble::TempPCHFile::~TempPCHFile() {
+  if (llvm::Error E = RemoveFileIfPresent())
+    llvm::report_fatal_error("failed destroying temporary PCH file: " +
+                             toString(std::move(E)));
+}
 
-void PrecompiledPreamble::TempPCHFile::RemoveFileIfPresent() {
+llvm::Error PrecompiledPreamble::TempPCHFile::RemoveFileIfPresent() {
   if (FilePath) {
-    TemporaryFiles::getInstance().removeFile(*FilePath);
+    if (llvm::Error E = TemporaryFiles::getInstance().removeFile(*FilePath))
+      return E;
     FilePath = None;
   }
+  return llvm::Error::success();
 }
 
 llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath() const {
Index: clang/lib/Frontend/DependencyFile.cpp
===================================================================
--- clang/lib/Frontend/DependencyFile.cpp
+++ clang/lib/Frontend/DependencyFile.cpp
@@ -311,7 +311,8 @@
 
 void DependencyFileGenerator::outputDependencyFile(DiagnosticsEngine &Diags) {
   if (SeenMissingHeader) {
-    llvm::sys::fs::remove(OutputFile);
+    if (std::error_code EC = llvm::sys::fs::remove(OutputFile))
+      Diags.Report(diag::err_fe_error_removing) << OutputFile << EC.message();
     return;
   }
 
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -631,7 +631,9 @@
   for (OutputFile &OF : OutputFiles) {
     if (!OF.TempFilename.empty()) {
       if (EraseFiles) {
-        llvm::sys::fs::remove(OF.TempFilename);
+        if (std::error_code EC = llvm::sys::fs::remove(OF.TempFilename))
+          getDiagnostics().Report(diag::err_fe_error_removing)
+              << OF.TempFilename << EC.message();
       } else {
         SmallString<128> NewOutFile(OF.Filename);
 
@@ -643,16 +645,21 @@
           getDiagnostics().Report(diag::err_unable_to_rename_temp)
             << OF.TempFilename << OF.Filename << ec.message();
 
-          llvm::sys::fs::remove(OF.TempFilename);
+          // Ignore errors removing a file when renaming already failed.
+          (void)llvm::sys::fs::remove(OF.TempFilename);
         }
       }
     } else if (!OF.Filename.empty() && EraseFiles)
-      llvm::sys::fs::remove(OF.Filename);
+      if (std::error_code EC = llvm::sys::fs::remove(OF.Filename))
+        getDiagnostics().Report(diag::err_fe_error_removing)
+            << OF.Filename << EC.message();
   }
   OutputFiles.clear();
   if (DeleteBuiltModules) {
     for (auto &Module : BuiltModules)
-      llvm::sys::fs::remove(Module.second);
+      if (std::error_code EC = llvm::sys::fs::remove(Module.second))
+        getDiagnostics().Report(diag::err_fe_error_removing)
+            << Module.second << EC.message();
     BuiltModules.clear();
   }
   NonSeekStream.reset();
@@ -1437,18 +1444,20 @@
       }
 
       // Remove the file.
-      llvm::sys::fs::remove(File->path());
+      if ((EC = llvm::sys::fs::remove(File->path())))
+        break;
 
-      // Remove the timestamp file.
-      std::string TimpestampFilename = File->path() + ".timestamp";
-      llvm::sys::fs::remove(TimpestampFilename);
+      std::string TimestampFilename = File->path() + ".timestamp";
+      if ((EC = llvm::sys::fs::remove(TimestampFilename)))
+        break;
     }
 
     // If we removed all of the files in the directory, remove the directory
     // itself.
     if (llvm::sys::fs::directory_iterator(Dir->path(), EC) ==
             llvm::sys::fs::directory_iterator() && !EC)
-      llvm::sys::fs::remove(Dir->path());
+      if ((EC = llvm::sys::fs::remove(Dir->path())))
+        break;
   }
 }
 
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -2290,9 +2290,10 @@
   }
 }
 
-bool ASTUnit::Save(StringRef File) {
+llvm::Error ASTUnit::Save(StringRef File) {
   if (HadModuleLoaderFatalFailure)
-    return true;
+    return llvm::createStringError(std::errc::io_error,
+                                   "module loader had a fatal failure");
 
   // Write to a temporary file and later rename it to the actual file, to avoid
   // possible race conditions.
@@ -2300,8 +2301,10 @@
   TempPath = File;
   TempPath += "-%%%%%%%%";
   int fd;
-  if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
-    return true;
+  if (std::error_code EC =
+          llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
+    return llvm::createStringError(EC, "creating unique file \"%s\" for AST",
+                                   TempPath.c_str());
 
   // FIXME: Can we somehow regenerate the stat cache here, or do we need to
   // unconditionally create a stat cache when we parse the file?
@@ -2310,16 +2313,19 @@
   serialize(Out);
   Out.close();
   if (Out.has_error()) {
+    llvm::Error E = llvm::createStringError(Out.error(), "AST serialization failed");
     Out.clear_error();
-    return true;
+    return E;
   }
 
-  if (llvm::sys::fs::rename(TempPath, File)) {
-    llvm::sys::fs::remove(TempPath);
-    return true;
+  if (std::error_code EC = llvm::sys::fs::rename(TempPath, File)) {
+    // Ignore failure to remove if we already fail to rename.
+    (void)llvm::sys::fs::remove(TempPath);
+    return llvm::createStringError(EC, "renaming \"%s\" to \"%s\" failed",
+                                   TempPath.c_str(), File.str().c_str());
   }
 
-  return false;
+  return llvm::Error::success();
 }
 
 static bool serializeUnit(ASTWriter &Writer,
Index: clang/include/clang/Frontend/PrecompiledPreamble.h
===================================================================
--- clang/include/clang/Frontend/PrecompiledPreamble.h
+++ clang/include/clang/Frontend/PrecompiledPreamble.h
@@ -17,6 +17,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/MD5.h"
 #include <cstddef>
 #include <memory>
@@ -156,7 +157,7 @@
     llvm::StringRef getFilePath() const;
 
   private:
-    void RemoveFileIfPresent();
+    llvm::Error RemoveFileIfPresent();
 
   private:
     llvm::Optional<std::string> FilePath;
Index: clang/include/clang/Frontend/ASTUnit.h
===================================================================
--- clang/include/clang/Frontend/ASTUnit.h
+++ clang/include/clang/Frontend/ASTUnit.h
@@ -22,12 +22,12 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
-#include "clang/Frontend/PrecompiledPreamble.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -38,6 +38,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -888,9 +889,8 @@
 
   /// Save this translation unit to a file with the given name.
   ///
-  /// \returns true if there was a file error or false if the save was
-  /// successful.
-  bool Save(StringRef File);
+  /// \returns Errors arising from file operations.
+  llvm::Error Save(StringRef File);
 
   /// Serialize this translation unit with the given output stream.
   ///
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -10,6 +10,7 @@
 
 let Component = "Frontend" in {
 
+def err_fe_error_removing : Error<"error removing '%0': %1">;
 def err_fe_error_opening : Error<"error opening '%0': %1">;
 def err_fe_error_reading : Error<"error reading '%0'">;
 def err_fe_error_reading_stdin : Error<"error reading stdin: %0">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to