akhuang updated this revision to Diff 346882.
akhuang added a comment.

Change to using TempFiles


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D102736

Files:
  clang/include/clang/Frontend/CompilerInstance.h
  clang/lib/Frontend/CompilerInstance.cpp
  llvm/lib/Support/Path.cpp
  llvm/lib/Support/Windows/Path.inc

Index: llvm/lib/Support/Windows/Path.inc
===================================================================
--- llvm/lib/Support/Windows/Path.inc
+++ llvm/lib/Support/Windows/Path.inc
@@ -560,11 +560,6 @@
   return errc::permission_denied;
 }
 
-static std::error_code rename_fd(int FromFD, const Twine &To) {
-  HANDLE FromHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FromFD));
-  return rename_handle(FromHandle, To);
-}
-
 std::error_code rename(const Twine &From, const Twine &To) {
   // Convert to utf-16.
   SmallVector<wchar_t, 128> WideFrom;
Index: llvm/lib/Support/Path.cpp
===================================================================
--- llvm/lib/Support/Path.cpp
+++ llvm/lib/Support/Path.cpp
@@ -1229,7 +1229,7 @@
   auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
   std::error_code RenameEC = setDeleteDisposition(H, false);
   if (!RenameEC) {
-    RenameEC = rename_fd(FD, Name);
+    RenameEC = rename_handle(H, Name);
     // If rename failed because it's cross-device, copy instead
     if (RenameEC ==
       std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
@@ -1261,7 +1261,6 @@
     return errorCodeToError(EC);
   }
   FD = -1;
-
   return errorCodeToError(RenameEC);
 }
 
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -704,6 +704,10 @@
 void CompilerInstance::clearOutputFiles(bool EraseFiles) {
   for (OutputFile &OF : OutputFiles) {
     if (EraseFiles) {
+      if (OF.TempFile) {
+        if (llvm::Error E = OF.TempFile->discard())
+          consumeError(std::move(E));
+      }
       if (!OF.TempFilename.empty()) {
         llvm::sys::fs::remove(OF.TempFilename);
         continue;
@@ -720,11 +724,22 @@
     // relative to that.
     SmallString<128> NewOutFile(OF.Filename);
     FileMgr->FixupRelativePath(NewOutFile);
-    std::error_code EC = llvm::sys::fs::rename(OF.TempFilename, NewOutFile);
-    if (!EC)
+
+    std::string ErrorMsg;
+    if (OF.TempFile) {
+      if (llvm::Error E = OF.TempFile->keep(NewOutFile))
+        ErrorMsg = toString(std::move(E));
+    } else {
+      if (std::error_code EC =
+              llvm::sys::fs::rename(OF.TempFilename, NewOutFile))
+        ErrorMsg = EC.message();
+    }
+
+    if (ErrorMsg.empty())
       continue;
+
     getDiagnostics().Report(diag::err_unable_to_rename_temp)
-        << OF.TempFilename << OF.Filename << EC.message();
+        << OF.TempFilename << OF.Filename << ErrorMsg;
 
     llvm::sys::fs::remove(OF.TempFilename);
   }
@@ -808,7 +823,8 @@
     }
   }
 
-  std::string TempFile;
+  std::string TempFileName;
+  Optional<llvm::sys::fs::TempFile> Temp;
   if (UseTemporary) {
     // Create a temporary file.
     // Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -821,9 +837,44 @@
     TempPath += OutputExtension;
     TempPath += ".tmp";
     int fd;
-    std::error_code EC = llvm::sys::fs::createUniqueFile(
-        TempPath, fd, TempPath,
-        Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text);
+#if _WIN32
+    // On Windows, use llvm::sys::fs::TempFile to write the output file so
+    // that it is deleted if the program crashes.
+    Expected<llvm::sys::fs::TempFile> ExpectedFile =
+        llvm::sys::fs::TempFile::create(TempPath);
+
+    llvm::Error E = handleErrors(
+        ExpectedFile.takeError(), [&](const llvm::ECError &E) -> llvm::Error {
+          std::error_code EC = E.convertToErrorCode();
+          if (CreateMissingDirectories &&
+              EC == llvm::errc::no_such_file_or_directory) {
+            StringRef Parent = llvm::sys::path::parent_path(OutputPath);
+            EC = llvm::sys::fs::create_directories(Parent);
+            if (!EC) {
+              ExpectedFile = llvm::sys::fs::TempFile::create(TempPath);
+              if (!ExpectedFile)
+                return llvm::errorCodeToError(
+                    llvm::errc::no_such_file_or_directory);
+            }
+          }
+          return llvm::errorCodeToError(EC);
+        });
+
+    if (E) {
+      consumeError(std::move(E));
+    } else {
+      Temp = std::move(ExpectedFile.get());
+      fd = Temp->FD;
+      TempPath = Temp->TmpName;
+
+      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/false));
+      OSFile = TempFileName = std::string(TempPath.str());
+    }
+#else
+    std::error_code EC;
+    EC = fs::createUniqueFile(TempPath, fd, TempPath,
+                              Binary ? llvm::sys::fs::OF_None
+                                     : llvm::sys::fs::OF_Text);
 
     if (CreateMissingDirectories &&
         EC == llvm::errc::no_such_file_or_directory) {
@@ -838,8 +889,9 @@
 
     if (!EC) {
       OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
-      OSFile = TempFile = std::string(TempPath.str());
+      OSFile = TempFileName = std::string(TempPath.str());
     }
+#endif
     // If we failed to create the temporary, fallback to writing to the file
     // directly. This handles the corner case where we cannot write to the
     // directory, but can write to the file.
@@ -862,7 +914,7 @@
   // Add the output file -- but don't try to remove "-", since this means we are
   // using stdin.
   OutputFiles.emplace_back(((OutputPath != "-") ? OutputPath : "").str(),
-                           std::move(TempFile));
+                           std::move(TempFileName), std::move(Temp));
 
   if (!Binary || OS->supportsSeeking())
     return std::move(OS);
Index: clang/include/clang/Frontend/CompilerInstance.h
===================================================================
--- clang/include/clang/Frontend/CompilerInstance.h
+++ clang/include/clang/Frontend/CompilerInstance.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/BuryPointer.h"
+#include "llvm/Support/FileSystem.h"
 #include <cassert>
 #include <list>
 #include <memory>
@@ -166,10 +167,12 @@
   struct OutputFile {
     std::string Filename;
     std::string TempFilename;
+    Optional<llvm::sys::fs::TempFile> TempFile;
 
-    OutputFile(std::string filename, std::string tempFilename)
-        : Filename(std::move(filename)), TempFilename(std::move(tempFilename)) {
-    }
+    OutputFile(std::string filename, std::string tempFilename,
+               Optional<llvm::sys::fs::TempFile> tempFile)
+        : Filename(std::move(filename)), TempFilename(std::move(tempFilename)),
+          TempFile(std::move(tempFile)) {}
   };
 
   /// The list of active output files.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to