]> granicus.if.org Git - clang/commitdiff
Bail on compilation as soon as a job fails.
authorJustin Lebar <jlebar@google.com>
Wed, 24 Feb 2016 21:49:28 +0000 (21:49 +0000)
committerJustin Lebar <jlebar@google.com>
Wed, 24 Feb 2016 21:49:28 +0000 (21:49 +0000)
Summary:
(Re-land of r260448, which was reverted in r260522 due to a test failure
in Driver/output-file-cleanup.c that only showed up in fresh builds.)

Previously we attempted to be smart; if one job failed, we'd run all
jobs that didn't depend on the failing job.

Problem is, this doesn't work well for e.g. CUDA compilation without
-save-temps.  In this case, the device-side and host-side Assemble
actions (which actually are responsible for preprocess, compile,
backend, and assemble, since we're not saving temps) are necessarily
distinct.  So our clever heuristic doesn't help us, and we repeat every
error message once for host and once for each device arch.

The main effect of this change, other than fixing CUDA, is that if you
pass multiple cc files to one instance of clang and you get a compile
error, we'll stop when the first cc1 job fails.

Reviewers: echristo

Subscribers: cfe-commits, jhen, echristo, tra, rafael

Differential Revision: http://reviews.llvm.org/D17217

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261774 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/Compilation.cpp
test/Driver/output-file-cleanup.c

index 71bccfa92d256658b9a0de2ecdcafa1b9d72c00e..b24d38161aa7b3c571ec5b4d9767a941c05c786e 100644 (file)
@@ -163,39 +163,17 @@ int Compilation::ExecuteCommand(const Command &C,
   return ExecutionFailed ? 1 : Res;
 }
 
-typedef SmallVectorImpl< std::pair<int, const Command *> > 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 {
+void Compilation::ExecuteJobs(
+    const JobList &Jobs,
+    SmallVectorImpl<std::pair<int, const Command *>> &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));
+      // 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;
+    }
   }
 }
 
index e907bd36077915a3b1a75ebcb4fcd7c8d7396071..314af4d6d37efcf23c6945674af1698d60616586 100644 (file)
@@ -38,6 +38,9 @@ invalid C code
 // RUN: test -f %t1.s
 // RUN: test ! -f %t2.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 %t1.c
 // RUN: echo "invalid C code" > %t2.c
 // RUN: touch %t3.c
@@ -46,6 +49,6 @@ invalid C code
 // RUN: cd %T && not %clang -S %t1.c %t2.c %t3.c %t4.c %t5.c
 // RUN: test -f %t1.s
 // RUN: test ! -f %t2.s
-// RUN: test -f %t3.s
+// RUN: test -f %t3.s
 // RUN: test ! -f %t4.s
-// RUN: test -f %t5.s
+// RUN: test -f %t5.s