Index: include/clang/Driver/Compilation.h =================================================================== --- include/clang/Driver/Compilation.h +++ include/clang/Driver/Compilation.h @@ -193,12 +193,13 @@ /// \return The result code of the subprocess. int ExecuteCommand(const Command &C, const Command *&FailingCommand) const; - /// ExecuteJob - Execute a single job. + /// ExecuteJobs - Execute a list of jobs. /// - /// \param FailingCommands - For non-zero results, this will be a vector of - /// failing commands and their associated result code. + /// \param StopOnFailure - If true, execution stops as soon as one job fails. + /// \param FailingCommands - Outparam that's set to the list of Commands that + /// failed, plus their associated result codes. void ExecuteJobs( - const JobList &Jobs, + const JobList &Jobs, bool StopOnFailure, SmallVectorImpl> &FailingCommands) const; /// initCompilationForDiagnostics - Remove stale state and suppress output Index: include/clang/Driver/Driver.h =================================================================== --- include/clang/Driver/Driver.h +++ include/clang/Driver/Driver.h @@ -192,6 +192,10 @@ /// Certain options suppress the 'no input files' warning. bool SuppressMissingInputWarning : 1; + /// Should we stop running all jobs as soon as one fails? If false, we run as + /// much as we can. + bool StopOnJobFailure : 1; + std::list TempFiles; std::list ResultFiles; Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1801,6 +1801,11 @@ def : Flag<["-"], "no-integrated-as">, Alias, Flags<[CC1Option, DriverOption]>; +def stop_on_failure : Flag<["-"], "stop-on-failure">, Flags<[DriverOption]>, + HelpText<"Stop running jobs as soon as one fails. This is the default during " + "CUDA compilation without --save-temps.">; +def nostop_on_failure : Flag<["-"], "nostop-on-failure">, Flags<[DriverOption]>; + def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>, HelpText<"Resolve file paths relative to the specified directory">; def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>, Index: lib/Driver/Compilation.cpp =================================================================== --- lib/Driver/Compilation.cpp +++ lib/Driver/Compilation.cpp @@ -188,14 +188,17 @@ return !ActionFailed(&C.getSource(), FailingCommands); } -void Compilation::ExecuteJobs(const JobList &Jobs, +void Compilation::ExecuteJobs(const JobList &Jobs, bool StopOnFailure, FailingCommandList &FailingCommands) const { for (const auto &Job : Jobs) { if (!InputsOk(Job, FailingCommands)) continue; const Command *FailingCommand = nullptr; - if (int Res = ExecuteCommand(Job, FailingCommand)) + if (int Res = ExecuteCommand(Job, FailingCommand)) { FailingCommands.push_back(std::make_pair(Res, FailingCommand)); + if (StopOnFailure) + return; + } } } Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -58,7 +58,8 @@ CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), - CCCUsePCH(true), SuppressMissingInputWarning(false) { + CCCUsePCH(true), SuppressMissingInputWarning(false), + StopOnJobFailure(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) @@ -503,6 +504,16 @@ InputList Inputs; BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); + // StopOnJobFailure defaults to false, except for CUDA compilations. + if (Arg *A = C->getArgs().getLastArg(options::OPT_stop_on_failure, + options::OPT_nostop_on_failure)) + StopOnJobFailure = A->getOption().matches(options::OPT_stop_on_failure); + else + StopOnJobFailure = + llvm::any_of(Inputs, [](const std::pair &I) { + return I.first == types::TY_CUDA; + }); + // Construct the list of abstract actions to perform for this compilation. On // MachO targets this uses the driver-driver and universal actions. if (TC.getTriple().isOSBinFormatMachO()) @@ -636,7 +647,7 @@ // Generate preprocessed output. SmallVector, 4> FailingCommands; - C.ExecuteJobs(C.getJobs(), FailingCommands); + C.ExecuteJobs(C.getJobs(), /* StopOnFailure = */ false, FailingCommands); // If any of the preprocessing commands failed, clean up and exit. if (!FailingCommands.empty()) { @@ -728,7 +739,7 @@ for (auto &Job : C.getJobs()) setUpResponseFiles(C, Job); - C.ExecuteJobs(C.getJobs(), FailingCommands); + C.ExecuteJobs(C.getJobs(), StopOnJobFailure, FailingCommands); // Remove temp files. C.CleanupFileList(C.getTempFiles());