Emit error diagnostic for a primary if all errors suppressed

This commit is contained in:
David Ungar
2018-05-10 20:58:55 -07:00
parent 6015709a92
commit 70aecfef36
8 changed files with 63 additions and 18 deletions

View File

@@ -101,6 +101,8 @@ public:
/// \returns true if an error occurred while finishing-up.
virtual bool finishProcessing() { return false; }
virtual bool hadOnlySuppressedFatalErrors() const { return false; }
};
/// \brief DiagnosticConsumer that discards all diagnostics.
@@ -165,6 +167,9 @@ private:
/// If null, diagnostics are suppressed.
Optional<DiagnosticConsumer *> ConsumerForSubsequentNotes = None;
bool WasAFatalDiagnosticSuppressed = false;
bool WasAFatalDiagnosticEmitted = false;
public:
/// Takes ownership of the DiagnosticConsumers specified in \p consumers.
///
@@ -181,6 +186,8 @@ public:
bool finishProcessing() override;
bool hadOnlySuppressedFatalErrors() const override;
private:
void computeConsumersOrderedByRange(SourceManager &SM);

View File

@@ -768,6 +768,8 @@ namespace swift {
ArrayRef<DiagnosticArgument> FormatArgs,
DiagnosticFormatOptions FormatOpts = DiagnosticFormatOptions());
bool hadOnlySuppressedFatalErrors() const;
private:
/// \brief Flush the active diagnostic.
void flushActiveDiagnostic();

View File

@@ -235,6 +235,8 @@ WARNING(cannot_assign_value_to_conditional_compilation_flag,none,
ERROR(error_optimization_remark_pattern, none, "%0 in '%1'",
(StringRef, StringRef))
ERROR(error_compilation_failed,none, "compilation failed", ())
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG

View File

@@ -176,17 +176,25 @@ void FileSpecificDiagnosticConsumer::handleDiagnostic(
break;
}
const bool isErrorFatal = Kind == DiagnosticKind::Error;
if (!specificConsumer.hasValue()) {
for (auto &subConsumer : SubConsumers) {
if (subConsumer.second) {
subConsumer.second->handleDiagnostic(SM, Loc, Kind, FormatString,
FormatArgs, Info);
WasAFatalDiagnosticEmitted |= isErrorFatal;
}
}
} else if (DiagnosticConsumer *c = specificConsumer.getValue())
} else if (DiagnosticConsumer *c = specificConsumer.getValue()) {
c->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
else
; // Suppress non-primary diagnostic in batch mode.
WasAFatalDiagnosticEmitted |= isErrorFatal;
} else { // Suppress non-primary diagnostic in batch mode.
WasAFatalDiagnosticSuppressed |= isErrorFatal;
}
}
bool FileSpecificDiagnosticConsumer::hadOnlySuppressedFatalErrors() const {
return WasAFatalDiagnosticSuppressed && !WasAFatalDiagnosticEmitted;
}
bool FileSpecificDiagnosticConsumer::finishProcessing() {

View File

@@ -259,6 +259,14 @@ bool DiagnosticEngine::finishProcessing() {
return hadError;
}
bool DiagnosticEngine::hadOnlySuppressedFatalErrors() const {
for (auto &Consumer : Consumers) {
if (Consumer->hadOnlySuppressedFatalErrors())
return true;
}
return false;
}
/// \brief Skip forward to one of the given delimiters.
///
/// \param Text The text to search through, which will be updated to point

View File

@@ -1651,6 +1651,9 @@ int swift::performFrontend(ArrayRef<const char *> Args,
auto finishDiagProcessing = [&](int retValue) -> int {
FinishDiagProcessingCheckRAII.CalledFinishDiagProcessing = true;
if (Instance->getDiags().hadOnlySuppressedFatalErrors())
Instance->getDiags().diagnose(SourceLoc(),
diag::error_compilation_failed);
bool err = Instance->getDiags().finishProcessing();
return retValue ? retValue : err;
};

View File

@@ -0,0 +1,24 @@
// To avoid redundant diagnostics showing up in Xcode, batch-mode must suppress diagnostics in
// non-primary files.
// But if the only fatal errors are suppressed ones, a "compilation failed" error must be emitted
// for the primary files so Xcode knows something happened.
//
// RUN: rm -f %t.*
// RUN: not %target-swift-frontend -typecheck -primary-file %s -serialize-diagnostics-path %t.main.dia -primary-file %S/../Inputs/empty.swift -serialize-diagnostics-path %t.empty.dia %S/Inputs/serialized-diagnostics-batch-mode-suppression-helper.swift 2> %t.stderr.txt
// RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
// RUN: c-index-test -read-diagnostics %t.empty.dia 2> %t.empty.txt
// Ensure there was an error:
// RUN: %FileCheck -check-prefix=ERROR %s <%t.stderr.txt
// ERROR: error:
// Ensure the error is in the serialized diagnostics:
// RUN: %FileCheck -check-prefix=COMPILATION-FAILED %s <%t.main.txt
// RUN: %FileCheck -check-prefix=COMPILATION-FAILED %s <%t.empty.txt
// COMPILATION-FAILED: compilation failed
func test(x: SomeType) {
}

View File

@@ -7,20 +7,11 @@
// RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
// RUN: c-index-test -read-diagnostics %t.empty.dia 2> %t.empty.txt
// Ensure there was an error:
// RUN: %FileCheck -check-prefix=NO-COMPILATION-FAILED %s <%t.main.txt
// RUN: %FileCheck -check-prefix=NO-COMPILATION-FAILED %s <%t.empty.txt
// NO-COMPILATION-FAILED-NOT: compilation failed
// RUN: %FileCheck -check-prefix=ERROR %s <%t.stderr.txt
// ERROR: error:
// Ensure the error is not in the serialized diagnostics:
// RUN: %FileCheck -check-prefix=NO-DIAGNOSTICS %s <%t.main.txt
// RUN: %FileCheck -check-prefix=NO-DIAGNOSTICS %s <%t.empty.txt
// NO-DIAGNOSTICS: Number of diagnostics: 0
// RUN: %FileCheck -check-prefix=NO-ERROR %s <%t.main.txt
// RUN: %FileCheck -check-prefix=NO-ERROR %s <%t.empty.txt
// NO-ERROR-NOT: error:
func test(x: SomeType) {
nonexistant(); // create a fatal error here
}