aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Driver/Compilation.cpp47
-rw-r--r--clang/test/Driver/cuda-bail-out.cu54
-rw-r--r--clang/test/Driver/output-file-cleanup.c15
-rw-r--r--clang/test/Driver/unix-conformance.c24
4 files changed, 119 insertions, 21 deletions
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index c27ea51..645da50 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -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;
}
}
}
diff --git a/clang/test/Driver/cuda-bail-out.cu b/clang/test/Driver/cuda-bail-out.cu
new file mode 100644
index 0000000..aaf7714
--- /dev/null
+++ b/clang/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
diff --git a/clang/test/Driver/output-file-cleanup.c b/clang/test/Driver/output-file-cleanup.c
index 74d64b0..e3f2bdb 100644
--- a/clang/test/Driver/output-file-cleanup.c
+++ b/clang/test/Driver/output-file-cleanup.c
@@ -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
diff --git a/clang/test/Driver/unix-conformance.c b/clang/test/Driver/unix-conformance.c
new file mode 100644
index 0000000..ddf77c7
--- /dev/null
+++ b/clang/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