Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -19,6 +19,7 @@ #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Filesystem.h" #include "lld/Common/Memory.h" #include "lld/Common/Timer.h" #include "lld/Common/Version.h" @@ -1273,6 +1274,12 @@ getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue()); } + // Fail early if an output file is not writable. + if (auto E = tryCreateFile(Config->OutputFile)) { + error("cannot open output file " + Config->OutputFile + ": " + E.message()); + return; + } + // Put the PDB next to the image if no /pdb flag was passed. if (ShouldCreatePDB && Config->PDBPath.empty()) { Config->PDBPath = Config->OutputFile; Index: lld/Common/CMakeLists.txt =================================================================== --- lld/Common/CMakeLists.txt +++ lld/Common/CMakeLists.txt @@ -5,6 +5,7 @@ add_lld_library(lldCommon Args.cpp ErrorHandler.cpp + Filesystem.cpp Memory.cpp Reproduce.cpp Strings.cpp Index: lld/Common/Filesystem.cpp =================================================================== --- lld/Common/Filesystem.cpp +++ lld/Common/Filesystem.cpp @@ -11,8 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "Filesystem.h" -#include "Config.h" +#include "lld/Common/Filesystem.h" #include "lld/Common/Threads.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/FileOutputBuffer.h" @@ -23,9 +22,7 @@ #include using namespace llvm; - using namespace lld; -using namespace lld::elf; // Removes a given file asynchronously. This is a performance hack, // so remove this when operating systems are improved. @@ -42,7 +39,7 @@ // // This function spawns a background thread to remove the file. // The calling thread returns almost immediately. -void elf::unlinkAsync(StringRef Path) { +void lld::unlinkAsync(StringRef Path) { // Removing a file is async on windows. #if defined(LLVM_ON_WIN32) sys::fs::remove(Path); @@ -77,7 +74,7 @@ // FileOutputBuffer doesn't touch a desitnation file until commit() // is called. We use that class without calling commit() to predict // if the given file is writable. -std::error_code elf::tryCreateFile(StringRef Path) { +std::error_code lld::tryCreateFile(StringRef Path) { if (Path.empty()) return std::error_code(); if (Path == "-") Index: lld/ELF/CMakeLists.txt =================================================================== --- lld/ELF/CMakeLists.txt +++ lld/ELF/CMakeLists.txt @@ -22,7 +22,6 @@ Driver.cpp DriverUtils.cpp EhFrame.cpp - Filesystem.cpp GdbIndex.cpp ICF.cpp InputFiles.cpp Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -25,7 +25,6 @@ #include "Driver.h" #include "Config.h" -#include "Filesystem.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" @@ -42,6 +41,7 @@ #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Filesystem.h" #include "lld/Common/Memory.h" #include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/Threads.h" Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -10,7 +10,6 @@ #include "Writer.h" #include "AArch64ErrataFix.h" #include "Config.h" -#include "Filesystem.h" #include "LinkerScript.h" #include "MapFile.h" #include "OutputSections.h" @@ -20,6 +19,7 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "lld/Common/Filesystem.h" #include "lld/Common/Memory.h" #include "lld/Common/Threads.h" #include "llvm/ADT/StringMap.h" Index: lld/include/lld/Common/Filesystem.h =================================================================== --- lld/include/lld/Common/Filesystem.h +++ lld/include/lld/Common/Filesystem.h @@ -7,17 +7,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_ELF_FILESYSTEM_H -#define LLD_ELF_FILESYSTEM_H +#ifndef LLD_COMMON_FILESYSTEM_H +#define LLD_COMMON_FILESYSTEM_H #include "lld/Common/LLVM.h" #include namespace lld { -namespace elf { void unlinkAsync(StringRef Path); std::error_code tryCreateFile(StringRef Path); -} // namespace elf } // namespace lld #endif Index: lld/test/COFF/driver.test =================================================================== --- lld/test/COFF/driver.test +++ lld/test/COFF/driver.test @@ -4,3 +4,7 @@ # RUN: lld-link --version | FileCheck -check-prefix=VERSION %s VERSION: {{LLD [0-9]+\.[0-9]+}} + +# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj +# RUN: not lld-link /out:/ %t.obj 2>&1 | FileCheck -check-prefix=DIR %s +DIR: cannot open output file