forked from OSchip/llvm-project
[Driver] Make clang/cc conforms to UNIX standard
Summary: This is basically reverting r261774 with a tweak for clang-cl. UNIX standard states: 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 The same goes for c89 or cc. And they are all alias or shims pointing to clang on Darwin. The original commit was intended for CUDA so the error message doesn't get emit twice for both host and device. It seems that the clang driver has been changed to model the CUDA dependency differently. Now the driver behaves the same without this commit. rdar://problem/32223263 Reviewers: thakis, dexonsmith, tra Reviewed By: tra Subscribers: jlebar, cfe-commits Differential Revision: https://reviews.llvm.org/D39502 llvm-svn: 317860
This commit is contained in:
parent
07d9f10374
commit
9278019eb3
|
@ -182,16 +182,51 @@ int Compilation::ExecuteCommand(const Command &C,
|
|||
return ExecutionFailed ? 1 : Res;
|
||||
}
|
||||
|
||||
void Compilation::ExecuteJobs(
|
||||
const JobList &Jobs,
|
||||
SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const {
|
||||
using FailingCommandList = SmallVectorImpl<std::pair<int, const Command *>>;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -41,18 +41,3 @@ invalid C code
|
|||
// 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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue