Merge pull request #19261 from davidungar/rdar-43438753-and-43033749-fix-batch-mode-no-diags-swift-4.2-branch

[Batch Mode] Very simple and safe fix for batch mode diagnostic suppression bug. Includes tests.
diff --git a/include/swift/AST/DiagnosticConsumer.h b/include/swift/AST/DiagnosticConsumer.h
index add8686..7d28dab 100644
--- a/include/swift/AST/DiagnosticConsumer.h
+++ b/include/swift/AST/DiagnosticConsumer.h
@@ -187,6 +187,7 @@
       ConsumerSpecificInfoForSubsequentNotes = None;
 
   bool HasAnErrorBeenConsumed = false;
+  bool HasAnErrorWithNoConsumerSpecificInfoBeenConsumed = false;
 
 public:
   /// Takes ownership of the DiagnosticConsumers specified in \p consumers.
diff --git a/lib/AST/DiagnosticConsumer.cpp b/lib/AST/DiagnosticConsumer.cpp
index 17ac91b..0b5b06c 100644
--- a/lib/AST/DiagnosticConsumer.cpp
+++ b/lib/AST/DiagnosticConsumer.cpp
@@ -172,6 +172,8 @@
     break;
   }
   if (!consumerSpecificInfo.hasValue()) {
+    HasAnErrorWithNoConsumerSpecificInfoBeenConsumed |=
+        Kind == DiagnosticKind::Error;
     for (auto &subConsumer : SubConsumers) {
       if (subConsumer.second) {
         subConsumer.second->handleDiagnostic(SM, Loc, Kind, FormatString,
@@ -205,6 +207,11 @@
     tellSubconsumersToInformDriverOfIncompleteBatchModeCompilation() const {
   if (!HasAnErrorBeenConsumed)
     return;
+  if (HasAnErrorWithNoConsumerSpecificInfoBeenConsumed) {
+    // An error was emitted, but not through a consumerSpecificInfo.
+    // Falling through would lose the error, so return.
+    return;
+  }
   for (auto &info : ConsumersOrderedByRange) {
     if (!info.hasAnErrorBeenEmitted && info.consumer)
       info.consumer->informDriverOfIncompleteBatchModeCompilation();
diff --git a/test/ClangImporter/diags_from_header.swift b/test/ClangImporter/diags_from_header.swift
index 5b213a0..6116692 100644
--- a/test/ClangImporter/diags_from_header.swift
+++ b/test/ClangImporter/diags_from_header.swift
@@ -1,6 +1,16 @@
-// RUN: not %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/diags_from_header.h 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
+// RUN: not %target-swift-frontend -typecheck %s -enable-objc-interop -import-objc-header %S/Inputs/diags_from_header.h -serialize-diagnostics-path %t.dia 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
+// RUN: test -s %t.dia
+// RUN: c-index-test -read-diagnostics %t.dia 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
+  
+// Also check batch mode (multiple primary files).
+// RUN: not %target-swift-frontend -typecheck -primary-file %s -primary-file %S/../Inputs/empty.swift -enable-objc-interop -import-objc-header %S/Inputs/diags_from_header.h -serialize-diagnostics-path %t.1.dia -serialize-diagnostics-path %t.2.dia 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
+// RUN: test -s %t.1.dia
+// RUN: c-index-test -read-diagnostics %t.1.dia 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
+// RUN: test -s %t.2.dia
+// RUN: c-index-test -read-diagnostics %t.2.dia 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-WARN
 
-// RUN: not %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/diags_from_header.h -Xcc -Wno-#warnings 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-NO-WARN
+// Verify that -Wno-* options are applied.
+// RUN: not %target-swift-frontend -typecheck %s -enable-objc-interop -import-objc-header %S/Inputs/diags_from_header.h -Xcc -Wno-#warnings 2>&1 | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-NO-WARN
 
 // CHECK-WARN: diags_from_header.h:{{.*}}:2: warning: "here is some warning about something"
 // CHECK-NO-WARN-NOT: warning about something
diff --git a/test/ClangImporter/diags_from_module.swift b/test/ClangImporter/diags_from_module.swift
index 8ca3a66..2d224dd 100644
--- a/test/ClangImporter/diags_from_module.swift
+++ b/test/ClangImporter/diags_from_module.swift
@@ -1,19 +1,39 @@
-// RUN: not %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -Xcc -D -Xcc FOO 2> %t.err.txt
-// RUN: %FileCheck -input-file=%t.err.txt %s
+// RUN: %empty-directory(%t)
+// RUN: not %target-swift-frontend -module-cache-path %t -enable-objc-interop -typecheck %s -F %S/Inputs/frameworks -serialize-diagnostics-path %t.dia -Xcc -D -Xcc FOO 2>&1 | %FileCheck %s
+// RUN: test -s %t.dia
+// RUN: c-index-test -read-diagnostics %t.dia 2>&1 | %FileCheck %s
+  
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -module-cache-path %t -enable-objc-interop -typecheck %s -F %S/Inputs/frameworks -serialize-diagnostics-path %t.warn.dia 2>&1 | %FileCheck %s -check-prefix CHECK-WARN
+// RUN: test -s %t.warn.dia
+// RUN: c-index-test -read-diagnostics %t.warn.dia 2>&1 | %FileCheck %s -check-prefix CHECK-WARN
+  
+// Also check batch mode (multiple primary files).
+// RUN: %empty-directory(%t)
+// RUN: not %target-swift-frontend -module-cache-path %t -enable-objc-interop -typecheck -primary-file %s -primary-file %S/../Inputs/empty.swift -F %S/Inputs/frameworks -serialize-diagnostics-path %t.1.dia -serialize-diagnostics-path %t.2.dia -Xcc -D -Xcc FOO 2>&1 | %FileCheck %s
+// RUN: test -s %t.1.dia
+// RUN: c-index-test -read-diagnostics %t.1.dia 2>&1 | %FileCheck %s
+// RUN: c-index-test -read-diagnostics %t.1.dia 2>&1 | %FileCheck %s -check-prefix CHECK-PRIMARY
+// RUN: test -s %t.2.dia
+// RUN: c-index-test -read-diagnostics %t.2.dia 2>&1 | %FileCheck %s
 
-// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks 2> %t.warn.txt
-// RUN: %FileCheck -input-file=%t.warn.txt %s -check-prefix=CHECK-WARN
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -module-cache-path %t -enable-objc-interop -typecheck -primary-file %s -primary-file %S/../Inputs/empty.swift -F %S/Inputs/frameworks -serialize-diagnostics-path %t.warn.1.dia -serialize-diagnostics-path %t.warn.2.dia 2>&1 | %FileCheck %s -check-prefix CHECK-WARN
+// RUN: test -s %t.1.dia
+// RUN: c-index-test -read-diagnostics %t.warn.1.dia 2>&1 | %FileCheck %s -check-prefix=CHECK-WARN
+// RUN: test -s %t.2.dia
+// RUN: c-index-test -read-diagnostics %t.warn.2.dia 2>&1 | %FileCheck %s -check-prefix=CHECK-WARN
 
-// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -Xcc -Wno-#warnings 2> %t.nowarn.txt
-// RUN: %FileCheck -input-file=%t.nowarn.txt %s -check-prefix=CHECK-NO-WARN -allow-empty
+// Verify that -Wno-* options are applied.
+// RUN: %empty-directory(%t)
 
-// XFAIL: linux
+// RUN: %target-swift-frontend -module-cache-path %t -enable-objc-interop -typecheck %s -F %S/Inputs/frameworks -Xcc -Wno-#warnings 2>&1 | %FileCheck -check-prefix CHECK-NO-WARN -allow-empty %s
 
 import Module
 
 // CHECK: Another.h:2:4: error: Module should have been built without -DFOO
 // CHECK: Sub2.h:2:9: error: could not build module 'Another'
-// CHECK: diags_from_module.swift:[[@LINE-4]]:8: error: could not build Objective-C module 'Module'
+// CHECK-PRIMARY: diags_from_module.swift:[[@LINE-4]]:8: error: could not build Objective-C module 'Module'
 
 // CHECK-WARN: Sub2.h:7:2: warning: here is some warning about something
 // FIXME: show the clang warning: <module-includes>:1:1: warning: umbrella header for module 'Module' does not include header 'NotInModule.h' [-Wincomplete-umbrella]