Index: lib/Driver/Compilation.cpp =================================================================== --- lib/Driver/Compilation.cpp +++ lib/Driver/Compilation.cpp @@ -182,16 +182,42 @@ return ExecutionFailed ? 1 : Res; } -void Compilation::ExecuteJobs( - const JobList &Jobs, - SmallVectorImpl> &FailingCommands) const { +typedef SmallVectorImpl< std::pair > 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 (const Action *AI : A->inputs()) + if (ActionFailed(AI, FailingCommands)) + return true; + + return false; +} + +static bool InputsOk(const Command &C, + const FailingCommandList &FailingCommands) { + return !ActionFailed(&C.getSource(), FailingCommands); +} + +void Compilation::ExecuteJobs(const JobList &Jobs, + FailingCommandList &FailingCommands) const { for (const auto &Job : Jobs) { + if (!InputsOk(Job, FailingCommands)) + continue; const Command *FailingCommand = nullptr; if (int Res = ExecuteCommand(Job, FailingCommand)) { FailingCommands.push_back(std::make_pair(Res, FailingCommand)); - // Bail as soon as one command fails, so we don't output duplicate error - // messages if we die on e.g. the same file. - return; + // Bail on error in cl mode. + if (TheDriver.IsCLMode()) + return; } } } Index: test/Driver/output-file-cleanup.c =================================================================== --- test/Driver/output-file-cleanup.c +++ test/Driver/output-file-cleanup.c @@ -53,6 +53,6 @@ // RUN: not %clang -S %t-dir/1.c %t-dir/2.c %t-dir/3.c %t-dir/4.c %t-dir/5.c // RUN: test -f %t-dir/1.s // RUN: test ! -f %t-dir/2.s -// RUN: test ! -f %t-dir/3.s +// RUN: test -f %t-dir/3.s // RUN: test ! -f %t-dir/4.s -// RUN: test ! -f %t-dir/5.s +// RUN: test -f %t-dir/5.s