[cfe-commits] r114187 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td include/clang/Frontend/CompilerInstance.h lib/Frontend/CompilerInstance.cpp test/CodeGen/2008-07-17-no-emit-on-error.c

Francois Pichet pichet2000 at gmail.com
Sat Sep 18 11:02:35 PDT 2010


This commit is failing some clang lit tests sporadically on Windows

for example:
error: unable to rename temporary 'D:/Dev/llvm/llvm_trunk/tools/clang/test/CodeG
enObjC/Output/ns-constant-strings.m.tmp-000000' to output file 'D:\Dev\llvm\llvm
_trunk\tools\clang\test\CodeGenObjC\Output\ns-constant-strings.m.tmp': 'Can't mo
ve 'D:/Dev/llvm/llvm_trunk/tools/clang/test/CodeGenObjC/Output/ns-constant-strin
gs.m.tmp-000000' to 'D:/Dev/llvm/llvm_trunk/tools/clang/test/CodeGenObjC/Output/
ns-constant-strings.m.tmp': Access is denied.


I am going to take a look at it.

On Fri, Sep 17, 2010 at 1:38 PM, Argyrios Kyrtzidis <akyrtzi at gmail.com> wrote:
> Author: akirtzidis
> Date: Fri Sep 17 12:38:48 2010
> New Revision: 114187
>
> URL: http://llvm.org/viewvc/llvm-project?rev=114187&view=rev
> Log:
> Use a temporary file for output which gets renamed after all the writing is finished.
>
> This mainly prevents failures and/or crashes when multiple processes try to read/write the same PCH file. (rdar://8392711&8294781); suggestion & review by Daniel!
>
> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
>    cfe/trunk/include/clang/Frontend/CompilerInstance.h
>    cfe/trunk/lib/Frontend/CompilerInstance.cpp
>    cfe/trunk/test/CodeGen/2008-07-17-no-emit-on-error.c
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=114187&r1=114186&r2=114187&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Fri Sep 17 12:38:48 2010
> @@ -69,6 +69,8 @@
>     DefaultFatal;
>  def err_fe_unable_to_open_output : Error<
>     "unable to open output file '%0': '%1'">;
> +def err_fe_unable_to_rename_temp : Error<
> +    "unable to rename temporary '%0' to output file '%1': '%2'">;
>  def err_fe_unable_to_open_logfile : Error<
>     "unable to open logfile file '%0': '%1'">;
>  def err_fe_pth_file_has_no_source_header : Error<
>
> Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=114187&r1=114186&r2=114187&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
> +++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Fri Sep 17 12:38:48 2010
> @@ -95,8 +95,23 @@
>   /// The frontend timer
>   llvm::OwningPtr<llvm::Timer> FrontendTimer;
>
> +  /// \brief Holds information about the output file.
> +  ///
> +  /// If TempFilename is not empty we must rename it to Filename at the end.
> +  /// TempFilename may be empty and Filename non empty if creating the temporary
> +  /// failed.
> +  struct OutputFile {
> +    std::string Filename;
> +    std::string TempFilename;
> +    llvm::raw_ostream *OS;
> +
> +    OutputFile(const std::string &filename, const std::string &tempFilename,
> +               llvm::raw_ostream *os)
> +      : Filename(filename), TempFilename(tempFilename), OS(os) { }
> +  };
> +
>   /// The list of active output files.
> -  std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
> +  std::list<OutputFile> OutputFiles;
>
>   void operator=(const CompilerInstance &);  // DO NOT IMPLEMENT
>   CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
> @@ -442,9 +457,8 @@
>
>   /// addOutputFile - Add an output file onto the list of tracked output files.
>   ///
> -  /// \param Path - The path to the output file, or empty.
> -  /// \param OS - The output stream, which should be non-null.
> -  void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS);
> +  /// \param OutFile - The output file info.
> +  void addOutputFile(const OutputFile &OutFile);
>
>   /// clearOutputFiles - Clear the output file list, destroying the contained
>   /// output streams.
> @@ -565,7 +579,8 @@
>   ///
>   /// If \arg OutputPath is empty, then createOutputFile will derive an output
>   /// path location as \arg BaseInput, with any suffix removed, and \arg
> -  /// Extension appended.
> +  /// Extension appended. If OutputPath is not stdout createOutputFile will
> +  /// create a new temporary file that must be renamed to OutputPath in the end.
>   ///
>   /// \param OutputPath - If given, the path to the output file.
>   /// \param Error [out] - On failure, the error message.
> @@ -575,11 +590,14 @@
>   /// \param Binary - The mode to open the file in.
>   /// \param ResultPathName [out] - If given, the result path name will be
>   /// stored here on success.
> +  /// \param TempPathName [out] - If given, the temporary file path name
> +  /// will be stored here on success.
>   static llvm::raw_fd_ostream *
>   createOutputFile(llvm::StringRef OutputPath, std::string &Error,
>                    bool Binary = true, llvm::StringRef BaseInput = "",
>                    llvm::StringRef Extension = "",
> -                   std::string *ResultPathName = 0);
> +                   std::string *ResultPathName = 0,
> +                   std::string *TempPathName = 0);
>
>   /// }
>   /// @name Initialization Utility Methods
>
> Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=114187&r1=114186&r2=114187&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
> +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri Sep 17 12:38:48 2010
> @@ -35,6 +35,7 @@
>  #include "llvm/System/Host.h"
>  #include "llvm/System/Path.h"
>  #include "llvm/System/Program.h"
> +#include "llvm/System/Signals.h"
>  using namespace clang;
>
>  CompilerInstance::CompilerInstance()
> @@ -370,18 +371,30 @@
>
>  // Output Files
>
> -void CompilerInstance::addOutputFile(llvm::StringRef Path,
> -                                     llvm::raw_ostream *OS) {
> -  assert(OS && "Attempt to add empty stream to output list!");
> -  OutputFiles.push_back(std::make_pair(Path, OS));
> +void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
> +  assert(OutFile.OS && "Attempt to add empty stream to output list!");
> +  OutputFiles.push_back(OutFile);
>  }
>
>  void CompilerInstance::clearOutputFiles(bool EraseFiles) {
> -  for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
> +  for (std::list<OutputFile>::iterator
>          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
> -    delete it->second;
> -    if (EraseFiles && !it->first.empty())
> -      llvm::sys::Path(it->first).eraseFromDisk();
> +    delete it->OS;
> +    if (!it->TempFilename.empty()) {
> +      llvm::sys::Path TempPath(it->TempFilename);
> +      if (EraseFiles)
> +        TempPath.eraseFromDisk();
> +      else {
> +        std::string Error;
> +        if (TempPath.renamePathOnDisk(llvm::sys::Path(it->Filename), &Error)) {
> +          getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
> +            << it->TempFilename << it->Filename << Error;
> +          TempPath.eraseFromDisk();
> +        }
> +      }
> +    } else if (!it->Filename.empty() && EraseFiles)
> +      llvm::sys::Path(it->Filename).eraseFromDisk();
> +
>   }
>   OutputFiles.clear();
>  }
> @@ -399,10 +412,11 @@
>                                    bool Binary,
>                                    llvm::StringRef InFile,
>                                    llvm::StringRef Extension) {
> -  std::string Error, OutputPathName;
> +  std::string Error, OutputPathName, TempPathName;
>   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
>                                               InFile, Extension,
> -                                              &OutputPathName);
> +                                              &OutputPathName,
> +                                              &TempPathName);
>   if (!OS) {
>     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
>       << OutputPath << Error;
> @@ -411,7 +425,8 @@
>
>   // Add the output file -- but don't try to remove "-", since this means we are
>   // using stdin.
> -  addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
> +  addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
> +                TempPathName, OS));
>
>   return OS;
>  }
> @@ -422,8 +437,9 @@
>                                    bool Binary,
>                                    llvm::StringRef InFile,
>                                    llvm::StringRef Extension,
> -                                   std::string *ResultPathName) {
> -  std::string OutFile;
> +                                   std::string *ResultPathName,
> +                                   std::string *TempPathName) {
> +  std::string OutFile, TempFile;
>   if (!OutputPath.empty()) {
>     OutFile = OutputPath;
>   } else if (InFile == "-") {
> @@ -436,15 +452,37 @@
>   } else {
>     OutFile = "-";
>   }
> +
> +  if (OutFile != "-") {
> +    llvm::sys::Path OutPath(OutFile);
> +    // Only create the temporary if we can actually write to OutPath, otherwise
> +    // we want to fail early.
> +    if (!OutPath.exists() ||
> +        (OutPath.isRegularFile() && OutPath.canWrite())) {
> +      // Create a temporary file.
> +      llvm::sys::Path TempPath(OutFile);
> +      if (!TempPath.createTemporaryFileOnDisk())
> +        TempFile = TempPath.str();
> +    }
> +  }
> +
> +  std::string OSFile = OutFile;
> +  if (!TempFile.empty())
> +    OSFile = TempFile;
>
>   llvm::OwningPtr<llvm::raw_fd_ostream> OS(
> -    new llvm::raw_fd_ostream(OutFile.c_str(), Error,
> +    new llvm::raw_fd_ostream(OSFile.c_str(), Error,
>                              (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
>   if (!Error.empty())
>     return 0;
>
> +  // Make sure the out stream file gets removed if we crash.
> +  llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
> +
>   if (ResultPathName)
>     *ResultPathName = OutFile;
> +  if (TempPathName)
> +    *TempPathName = TempFile;
>
>   return OS.take();
>  }
>
> Modified: cfe/trunk/test/CodeGen/2008-07-17-no-emit-on-error.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/2008-07-17-no-emit-on-error.c?rev=114187&r1=114186&r2=114187&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGen/2008-07-17-no-emit-on-error.c (original)
> +++ cfe/trunk/test/CodeGen/2008-07-17-no-emit-on-error.c Fri Sep 17 12:38:48 2010
> @@ -1,6 +1,7 @@
>  // RUN: rm -f %t1.bc
>  // RUN: %clang_cc1 -DPASS %s -emit-llvm-bc -o %t1.bc
>  // RUN: test -f %t1.bc
> +// RUN: rm -f %t1.bc
>  // RUN: not %clang_cc1 %s -emit-llvm-bc -o %t1.bc
>  // RUN: not test -f %t1.bc
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list