diff options
Diffstat (limited to 'lib/Driver/Compilation.cpp')
-rw-r--r-- | lib/Driver/Compilation.cpp | 128 |
1 files changed, 86 insertions, 42 deletions
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 124e50c..1bff4a3 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -8,20 +8,18 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Compilation.h" - #include "clang/Driver/Action.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" - #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Program.h" -#include <sys/stat.h> +#include "llvm/Support/raw_ostream.h" #include <errno.h> +#include <sys/stat.h> using namespace clang::driver; using namespace clang; @@ -113,7 +111,7 @@ static bool skipArg(const char *Flag, bool &SkipNextArg) { bool Res = llvm::StringSwitch<bool>(Flag) .Cases("-I", "-MF", "-MT", "-MQ", true) .Cases("-o", "-coverage-file", "-dependency-file", true) - .Cases("-fdebug-compilation-dir", "-fmodule-cache-path", "-idirafter", true) + .Cases("-fdebug-compilation-dir", "-idirafter", true) .Cases("-include", "-include-pch", "-internal-isystem", true) .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true) .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true) @@ -201,39 +199,56 @@ void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const { } } +bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { + llvm::sys::Path P(File); + std::string Error; + + // Don't try to remove files which we don't have write access to (but may be + // able to remove), or non-regular files. Underlying tools may have + // intentionally not overwritten them. + if (!P.canWrite() || !P.isRegularFile()) + return true; + + if (P.eraseFromDisk(false, &Error)) { + // Failure is only failure if the file exists and is "regular". There is + // a race condition here due to the limited interface of + // llvm::sys::Path, we want to know if the removal gave ENOENT. + + // FIXME: Grumble, P.exists() is broken. PR3837. + struct stat buf; + if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG : + (errno != ENOENT)) { + if (IssueErrors) + getDriver().Diag(clang::diag::err_drv_unable_to_remove_file) + << Error; + return false; + } + } + return true; +} + bool Compilation::CleanupFileList(const ArgStringList &Files, bool IssueErrors) const { bool Success = true; - for (ArgStringList::const_iterator - it = Files.begin(), ie = Files.end(); it != ie; ++it) { + it = Files.begin(), ie = Files.end(); it != ie; ++it) + Success &= CleanupFile(*it, IssueErrors); + return Success; +} - llvm::sys::Path P(*it); - std::string Error; +bool Compilation::CleanupFileMap(const ArgStringMap &Files, + const JobAction *JA, + bool IssueErrors) const { + bool Success = true; + for (ArgStringMap::const_iterator + it = Files.begin(), ie = Files.end(); it != ie; ++it) { - // Don't try to remove files which we don't have write access to (but may be - // able to remove). Underlying tools may have intentionally not overwritten - // them. - if (!P.canWrite()) + // If specified, only delete the files associated with the JobAction. + // Otherwise, delete all files in the map. + if (JA && it->first != JA) continue; - - if (P.eraseFromDisk(false, &Error)) { - // Failure is only failure if the file exists and is "regular". There is - // a race condition here due to the limited interface of - // llvm::sys::Path, we want to know if the removal gave ENOENT. - - // FIXME: Grumble, P.exists() is broken. PR3837. - struct stat buf; - if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG : - (errno != ENOENT)) { - if (IssueErrors) - getDriver().Diag(clang::diag::err_drv_unable_to_remove_file) - << Error; - Success = false; - } - } + Success &= CleanupFile(it->second, IssueErrors); } - return Success; } @@ -275,11 +290,12 @@ int Compilation::ExecuteCommand(const Command &C, } std::string Error; + bool ExecutionFailed; int Res = llvm::sys::Program::ExecuteAndWait(Prog, Argv, /*env*/0, Redirects, /*secondsToWait*/0, /*memoryLimit*/0, - &Error); + &Error, &ExecutionFailed); if (!Error.empty()) { assert(Res && "Error string set with 0 result code!"); getDriver().Diag(clang::diag::err_drv_command_failure) << Error; @@ -289,24 +305,51 @@ int Compilation::ExecuteCommand(const Command &C, FailingCommand = &C; delete[] Argv; - return Res; + return ExecutionFailed ? 1 : Res; +} + +typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList; + +static bool ActionFailed(const Action *A, + const FailingCommandList &FailingCommands) { + + if (FailingCommands.empty()) + return false; + + for (FailingCommandList::const_iterator CI = FailingCommands.begin(), + CE = FailingCommands.end(); CI != CE; ++CI) + if (A == &(CI->second->getSource())) + return true; + + for (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI) + if (ActionFailed(*AI, FailingCommands)) + return true; + + return false; } -int Compilation::ExecuteJob(const Job &J, - const Command *&FailingCommand) const { +static bool InputsOk(const Command &C, + const FailingCommandList &FailingCommands) { + return !ActionFailed(&C.getSource(), FailingCommands); +} + +void Compilation::ExecuteJob(const Job &J, + FailingCommandList &FailingCommands) const { if (const Command *C = dyn_cast<Command>(&J)) { - return ExecuteCommand(*C, FailingCommand); + if (!InputsOk(*C, FailingCommands)) + return; + const Command *FailingCommand = 0; + if (int Res = ExecuteCommand(*C, FailingCommand)) + FailingCommands.push_back(std::make_pair(Res, FailingCommand)); } else { const JobList *Jobs = cast<JobList>(&J); - for (JobList::const_iterator - it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) - if (int Res = ExecuteJob(**it, FailingCommand)) - return Res; - return 0; + for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end(); + it != ie; ++it) + ExecuteJob(**it, FailingCommands); } } -void Compilation::initCompilationForDiagnostics(void) { +void Compilation::initCompilationForDiagnostics() { // Free actions and jobs. DeleteContainerPointers(Actions); Jobs.clear(); @@ -314,6 +357,7 @@ void Compilation::initCompilationForDiagnostics(void) { // Clear temporary/results file lists. TempFiles.clear(); ResultFiles.clear(); + FailureResultFiles.clear(); // Remove any user specified output. Claim any unclaimed arguments, so as // to avoid emitting warnings about unused args. @@ -331,6 +375,6 @@ void Compilation::initCompilationForDiagnostics(void) { Redirects[2] = new const llvm::sys::Path(); } -StringRef Compilation::getSysRoot(void) const { +StringRef Compilation::getSysRoot() const { return getDriver().SysRoot; } |