Frontend: Don't automatically create missing directories when using temporary files with createOutputFile()

- This would otherwise happen as a side effect of llvm::sys::fs::unique_file creating parent directories.

llvm-svn: 151960
This commit is contained in:
Daniel Dunbar
2012-03-03 00:36:02 +00:00
parent 62a58f4928
commit b9c62c0773
3 changed files with 28 additions and 9 deletions

View File

@@ -586,7 +586,8 @@ public:
bool Binary = true, bool RemoveFileOnSignal = true, bool Binary = true, bool RemoveFileOnSignal = true,
StringRef BaseInput = "", StringRef BaseInput = "",
StringRef Extension = "", StringRef Extension = "",
bool UseTemporary = false); bool UseTemporary = false,
bool CreateMissingDirectories = false);
/// Create a new output file, optionally deriving the output path name. /// Create a new output file, optionally deriving the output path name.
/// ///
@@ -606,7 +607,9 @@ public:
/// llvm::sys::RemoveFileOnSignal. Note that this is not safe for /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for
/// multithreaded use, as the underlying signal mechanism is not reentrant /// multithreaded use, as the underlying signal mechanism is not reentrant
/// \param UseTemporary - Create a new temporary file that must be renamed to /// \param UseTemporary - Create a new temporary file that must be renamed to
/// OutputPath in the end /// OutputPath in the end.
/// \param CreateMissingDirectories - When \arg UseTemporary is true, create
/// missing directories in the output path.
/// \param ResultPathName [out] - If given, the result path name will be /// \param ResultPathName [out] - If given, the result path name will be
/// stored here on success. /// stored here on success.
/// \param TempPathName [out] - If given, the temporary file path name /// \param TempPathName [out] - If given, the temporary file path name
@@ -617,6 +620,7 @@ public:
StringRef BaseInput = "", StringRef BaseInput = "",
StringRef Extension = "", StringRef Extension = "",
bool UseTemporary = false, bool UseTemporary = false,
bool CreateMissingDirectories = false,
std::string *ResultPathName = 0, std::string *ResultPathName = 0,
std::string *TempPathName = 0); std::string *TempPathName = 0);

View File

@@ -478,12 +478,14 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
bool Binary, bool RemoveFileOnSignal, bool Binary, bool RemoveFileOnSignal,
StringRef InFile, StringRef InFile,
StringRef Extension, StringRef Extension,
bool UseTemporary) { bool UseTemporary,
bool CreateMissingDirectories) {
std::string Error, OutputPathName, TempPathName; std::string Error, OutputPathName, TempPathName;
llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
RemoveFileOnSignal, RemoveFileOnSignal,
InFile, Extension, InFile, Extension,
UseTemporary, UseTemporary,
CreateMissingDirectories,
&OutputPathName, &OutputPathName,
&TempPathName); &TempPathName);
if (!OS) { if (!OS) {
@@ -508,8 +510,12 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
StringRef InFile, StringRef InFile,
StringRef Extension, StringRef Extension,
bool UseTemporary, bool UseTemporary,
bool CreateMissingDirectories,
std::string *ResultPathName, std::string *ResultPathName,
std::string *TempPathName) { std::string *TempPathName) {
assert((!CreateMissingDirectories || UseTemporary) &&
"CreateMissingDirectories is only allowed when using temporary files");
std::string OutFile, TempFile; std::string OutFile, TempFile;
if (!OutputPath.empty()) { if (!OutputPath.empty()) {
OutFile = OutputPath; OutFile = OutputPath;
@@ -528,12 +534,20 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
std::string OSFile; std::string OSFile;
if (UseTemporary && OutFile != "-") { if (UseTemporary && OutFile != "-") {
llvm::sys::Path OutPath(OutFile); // Only create the temporary if the parent directory exists (or create
// Only create the temporary if we can actually write to OutPath, otherwise // missing directories is true) and we can actually write to OutPath,
// we want to fail early. // otherwise we want to fail early.
SmallString<256> AbsPath(OutputPath);
llvm::sys::fs::make_absolute(AbsPath);
llvm::sys::Path OutPath(AbsPath);
bool ParentExists = false;
if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()),
ParentExists))
ParentExists = false;
bool Exists; bool Exists;
if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) || if ((CreateMissingDirectories || ParentExists) &&
(OutPath.isRegularFile() && OutPath.canWrite())) { ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) ||
(OutPath.isRegularFile() && OutPath.canWrite()))) {
// Create a temporary file. // Create a temporary file.
SmallString<128> TempPath; SmallString<128> TempPath;
TempPath = OutFile; TempPath = OutFile;

View File

@@ -340,7 +340,8 @@ bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
// We use a temporary to avoid race conditions. // We use a temporary to avoid race conditions.
OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
/*RemoveFileOnSignal=*/false, InFile, /*RemoveFileOnSignal=*/false, InFile,
/*Extension=*/"", /*useTemporary=*/true); /*Extension=*/"", /*useTemporary=*/true,
/*CreateMissingDirectories=*/true);
if (!OS) if (!OS)
return true; return true;