Index: cfe/trunk/lib/Driver/Compilation.cpp =================================================================== --- cfe/trunk/lib/Driver/Compilation.cpp +++ cfe/trunk/lib/Driver/Compilation.cpp @@ -182,16 +182,51 @@ return ExecutionFailed ? 1 : Res; } -void Compilation::ExecuteJobs( - const JobList &Jobs, - SmallVectorImpl> &FailingCommands) const { +using FailingCommandList = SmallVectorImpl>; + +static bool ActionFailed(const Action *A, + const FailingCommandList &FailingCommands) { + + if (FailingCommands.empty()) + return false; + + // CUDA can have the same input source code compiled multiple times so do not + // compiled again if there are already failures. It is OK to abort the CUDA + // pipeline on errors. + if (A->isOffloading(Action::OFK_Cuda)) + return true; + + for (const auto &CI : FailingCommands) + 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 { + // According to UNIX standard, driver need to continue compiling all the + // inputs on the command line even one of them failed. + // In all but CLMode, execute all the jobs unless the necessary inputs for the + // job is missing due to previous failures. 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 as soon as one command fails in cl driver mode. + if (TheDriver.IsCLMode()) + return; } } } Index: cfe/trunk/test/Driver/cuda-bail-out.cu =================================================================== --- cfe/trunk/test/Driver/cuda-bail-out.cu +++ cfe/trunk/test/Driver/cuda-bail-out.cu @@ -0,0 +1,54 @@ +// Test clang driver bails out after one error during CUDA compilation. + +// REQUIRES: clang-driver +// REQUIRES: powerpc-registered-target +// REQUIRES: nvptx-registered-target + +#ifdef FORCE_ERROR +#error compilation failed +#endif + +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DFORCE_ERROR %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DFORCE_ERROR --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_60 \ +// RUN: %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DFORCE_ERROR --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_60 \ +// RUN: --cuda-device-only %s 2>&1 | FileCheck %s + +#if defined(ERROR_HOST) && !defined(__CUDA_ARCH__) +#error compilation failed +#endif + +#if defined(ERROR_SM35) && (__CUDA_ARCH__ == 350) +#error compilation failed +#endif + +#if defined(ERROR_SM60) && (__CUDA_ARCH__ == 600) +#error compilation failed +#endif + +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_HOST --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_60 \ +// RUN: %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_SM35 --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_60 \ +// RUN: --cuda-device-only %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_SM60 --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_60 \ +// RUN: --cuda-device-only %s 2>&1 | FileCheck %s + +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_HOST -DERROR_SM35 --cuda-gpu-arch=sm_35 \ +// RUN: --cuda-gpu-arch=sm_60 %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_HOST -DERROR_SM60 --cuda-gpu-arch=sm_35 \ +// RUN: --cuda-gpu-arch=sm_60 %s 2>&1 | FileCheck %s +// RUN: not %clang -target powerpc64le-ibm-linux-gnu -fsyntax-only -nocudalib \ +// RUN: -nocudainc -DERROR_SM35 -DERROR_SM60 --cuda-gpu-arch=sm_35 \ +// RUN: --cuda-gpu-arch=sm_60 %s 2>&1 | FileCheck %s + + +// CHECK: error: compilation failed +// CHECK-NOT: error: compilation failed Index: cfe/trunk/test/Driver/output-file-cleanup.c =================================================================== --- cfe/trunk/test/Driver/output-file-cleanup.c +++ cfe/trunk/test/Driver/output-file-cleanup.c @@ -41,18 +41,3 @@ // RUN: not %clang -S %t-dir/1.c %t-dir/2.c // RUN: test -f %t-dir/1.s // RUN: test ! -f %t-dir/2.s - -// When given multiple .c files to compile, clang compiles them in order until -// it hits an error, at which point it stops. -// -// RUN: touch %t-dir/1.c -// RUN: echo "invalid C code" > %t-dir/2.c -// RUN: touch %t-dir/3.c -// RUN: echo "invalid C code" > %t-dir/4.c -// RUN: touch %t-dir/5.c -// 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/4.s -// RUN: test ! -f %t-dir/5.s Index: cfe/trunk/test/Driver/unix-conformance.c =================================================================== --- cfe/trunk/test/Driver/unix-conformance.c +++ cfe/trunk/test/Driver/unix-conformance.c @@ -0,0 +1,24 @@ +// Check UNIX conformance for cc/c89/c99 +// When c99 encounters a compilation error that causes an object file not to be +// created, it shall write a diagnostic to standard error and continue to +// compile other source code operands, but it shall not perform the link phase +// and it shall return a non-zero exit status. + +// When given multiple .c files to compile, clang compiles them in order until +// it hits an error, at which point it stops. +// +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir +// RUN: cd %t-dir +// +// RUN: touch %t-dir/1.c +// RUN: echo "invalid C code" > %t-dir/2.c +// RUN: touch %t-dir/3.c +// RUN: echo "invalid C code" > %t-dir/4.c +// RUN: touch %t-dir/5.c +// 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/4.s +// RUN: test -f %t-dir/5.s