From 4c4df4520df20ec17d84aa2261f098ec278e1dab Mon Sep 17 00:00:00 2001
From: Chad Rosier <mcrosier@apple.com>
Date: Wed, 27 Feb 2013 18:46:04 +0000
Subject: [PATCH] [driver] The failure of any phase (e.g., preprocess, compile,
 assemble) for a single translation unit should prevent later phases from
 executing.  Otherwise, this generates lots of noise in build systems.  This a
 fallout from r173825. Patch by Matthew Curtis <mcurtis@codeaurora.org>.
 rdar://13298009

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176198 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Driver/Compilation.cpp                | 29 ++++++++++++++++++++++-
 test/Driver/inhibit-downstream-commands.c |  5 ++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 test/Driver/inhibit-downstream-commands.c

diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index df904f06b7d..db948a5bfe9 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -307,9 +307,36 @@ int Compilation::ExecuteCommand(const Command &C,
   return 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 (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI)
+    if (ActionFailed(*AI, FailingCommands))
+      return true;
+
+  return false;
+}
+
+static bool InputsOk(const Command &C,
+                     const FailingCommandList &FailingCommands) {
+  return !ActionFailed(&C.getSource(), FailingCommands);
+}
+
 void Compilation::ExecuteJob(const Job &J,
-    SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const {
+                             FailingCommandList &FailingCommands) const {
   if (const Command *C = dyn_cast<Command>(&J)) {
+    if (!InputsOk(*C, FailingCommands))
+      return;
     const Command *FailingCommand = 0;
     if (int Res = ExecuteCommand(*C, FailingCommand))
       FailingCommands.push_back(std::make_pair(Res, FailingCommand));
diff --git a/test/Driver/inhibit-downstream-commands.c b/test/Driver/inhibit-downstream-commands.c
new file mode 100644
index 00000000000..e06fdb1a3de
--- /dev/null
+++ b/test/Driver/inhibit-downstream-commands.c
@@ -0,0 +1,5 @@
+// RUN: %clang -no-integrated-as %s 2>&1 | FileCheck %s
+// CHECK: error: unknown type name 'invalid'
+// CHECK-NOT: clang: error: assembler command failed 
+// CHECK-NOT: clang: error: linker command failed
+invalid C code!
-- 
GitLab