Skip to content

Commit 411e2a1

Browse files
committed
Merge remote-tracking branch 'milseman/suppress_warnings_api'
2 parents b5d5d82 + 31314b1 commit 411e2a1

File tree

2 files changed

+126
-52
lines changed

2 files changed

+126
-52
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,71 @@ namespace swift {
378378
return fixItReplaceChars(Start, End, {});
379379
}
380380
};
381+
382+
/// \brief Class to track, map, and remap diagnostic severity and fatality
383+
///
384+
class DiagnosticState {
385+
public:
386+
/// \brief Describes the current behavior to take with a diagnostic
387+
enum class Behavior {
388+
Unspecified,
389+
Ignore,
390+
Note,
391+
Warn,
392+
Err,
393+
Fatal,
394+
};
395+
396+
private:
397+
/// \brief Whether we should continue to emit diagnostics, even after a
398+
/// fatal error
399+
bool showDiagnosticsAfterFatalError = false;
400+
401+
/// \brief Don't emit any warnings
402+
bool ignoreAllWarnings = false;
403+
404+
/// \brief Whether a fatal error has occurred
405+
bool fatalErrorOccurred = false;
406+
407+
/// \brief Whether any error diagnostics have been emitted.
408+
bool anyErrorOccurred = false;
409+
410+
/// \brief Track the previous emitted Behavior, useful for notes
411+
Behavior previousBehavior = Behavior::Unspecified;
412+
413+
public:
414+
DiagnosticState() {}
415+
416+
/// \brief Figure out the Behavior for the given diagnostic
417+
Behavior getBehavior(const Diagnostic &);
418+
419+
bool hadAnyError() const { return anyErrorOccurred; }
420+
bool hasFatalErrorOccurred() const { return fatalErrorOccurred; }
421+
422+
void setShowDiagnosticsAfterFatalError(bool val = true) {
423+
showDiagnosticsAfterFatalError = val;
424+
}
425+
426+
/// \brief Whether to skip emitting warnings
427+
void setIgnoreAllWarnings(bool val) { ignoreAllWarnings = val; }
428+
bool getIgnoreAllWarnings() const { return ignoreAllWarnings; }
429+
430+
void resetHadAnyError() {
431+
anyErrorOccurred = false;
432+
fatalErrorOccurred = false;
433+
}
434+
435+
private:
436+
/// \returns true if diagnostic is marked as fatal.
437+
bool isDiagnosticFatal(DiagID ID) const;
438+
439+
// Make the state movable only
440+
DiagnosticState(const DiagnosticState &) = delete;
441+
const DiagnosticState &operator=(const DiagnosticState &) = delete;
442+
443+
DiagnosticState(DiagnosticState &&) = default;
444+
DiagnosticState &operator=(DiagnosticState &&) = default;
445+
};
381446

382447
/// \brief Class responsible for formatting diagnostics and presenting them
383448
/// to the user.
@@ -390,19 +455,7 @@ namespace swift {
390455
/// emitting diagnostics.
391456
SmallVector<DiagnosticConsumer *, 2> Consumers;
392457

393-
/// HadAnyError - True if any error diagnostics have been emitted.
394-
bool HadAnyError;
395-
396-
enum class FatalErrorState {
397-
None,
398-
JustEmitted,
399-
Fatal
400-
};
401-
402-
/// Sticky flag set to \c true when a fatal error is emitted.
403-
FatalErrorState FatalState = FatalErrorState::None;
404-
405-
bool ShowDiagnosticsAfterFatalError = false;
458+
DiagnosticState state;
406459

407460
/// \brief The currently active diagnostic, if there is one.
408461
Optional<Diagnostic> ActiveDiagnostic;
@@ -424,25 +477,28 @@ namespace swift {
424477

425478
public:
426479
explicit DiagnosticEngine(SourceManager &SourceMgr)
427-
: SourceMgr(SourceMgr), HadAnyError(false), ActiveDiagnostic() {
480+
: SourceMgr(SourceMgr), state(), ActiveDiagnostic() {
428481
}
429482

430483
/// hadAnyError - return true if any *error* diagnostics have been emitted.
431-
bool hadAnyError() const {
432-
return HadAnyError;
433-
}
484+
bool hadAnyError() const { return state.hadAnyError(); }
434485

435486
bool hasFatalErrorOccurred() const {
436-
return FatalState != FatalErrorState::None;
487+
return state.hasFatalErrorOccurred();
437488
}
438489

439-
void setShowDiagnosticsAfterFatalError(bool Val = true) {
440-
ShowDiagnosticsAfterFatalError = Val;
490+
void setShowDiagnosticsAfterFatalError(bool val = true) {
491+
state.setShowDiagnosticsAfterFatalError(val);
492+
}
493+
494+
/// \brief Whether to skip emitting warnings
495+
void setIgnoreAllWarnings(bool val) { state.setIgnoreAllWarnings(val); }
496+
bool getIgnoreAllWarnings() const {
497+
return state.getIgnoreAllWarnings();
441498
}
442499

443500
void resetHadAnyError() {
444-
HadAnyError = false;
445-
FatalState = FatalErrorState::None;
501+
state.resetHadAnyError();
446502
}
447503

448504
/// \brief Add an additional DiagnosticConsumer to receive diagnostics.
@@ -572,10 +628,7 @@ namespace swift {
572628

573629
/// \returns true if diagnostic is marked with PointsToFirstBadToken
574630
/// option.
575-
bool isDiagnosticPointsToFirstBadToken(DiagID ID) const;
576-
577-
/// \returns true if diagnostic is marked as fatal.
578-
bool isDiagnosticFatal(DiagID ID) const;
631+
bool isDiagnosticPointsToFirstBadToken(DiagID id) const;
579632

580633
private:
581634
/// \brief Flush the active diagnostic.

lib/AST/DiagnosticEngine.cpp

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ bool DiagnosticEngine::isDiagnosticPointsToFirstBadToken(DiagID ID) const {
180180
return StoredInfo.Options == DiagnosticOptions::PointsToFirstBadToken;
181181
}
182182

183-
bool DiagnosticEngine::isDiagnosticFatal(DiagID ID) const {
183+
bool DiagnosticState::isDiagnosticFatal(DiagID ID) const {
184184
const StoredDiagnosticInfo &StoredInfo =
185185
StoredDiagnosticInfos[(unsigned) ID];
186186
return StoredInfo.Options == DiagnosticOptions::Fatal;
@@ -449,6 +449,48 @@ static void formatDiagnosticText(StringRef InText,
449449
}
450450
}
451451

452+
DiagnosticState::Behavior DiagnosticState::getBehavior(const Diagnostic &diag) {
453+
auto set = [this](DiagnosticState::Behavior lvl) {
454+
if (lvl == Behavior::Fatal) {
455+
fatalErrorOccurred = true;
456+
anyErrorOccurred = true;
457+
} else if (lvl == Behavior::Err) {
458+
anyErrorOccurred = true;
459+
}
460+
461+
previousBehavior = lvl;
462+
return lvl;
463+
};
464+
465+
auto diagKind = StoredDiagnosticInfos[(unsigned)diag.getID()].Kind;
466+
467+
// Notes relating to ignored diagnostics should also be ignored
468+
if (previousBehavior == Behavior::Ignore && diagKind == DiagnosticKind::Note)
469+
return set(Behavior::Ignore);
470+
471+
// Suppress diagnostics when in a fatal state, except for follow-on notes
472+
// about the original fatal diag
473+
if (fatalErrorOccurred) {
474+
bool emitAnyways = showDiagnosticsAfterFatalError ||
475+
(diagKind == DiagnosticKind::Note &&
476+
previousBehavior != Behavior::Ignore);
477+
if (!emitAnyways)
478+
return set(Behavior::Ignore);
479+
} else if (isDiagnosticFatal(diag.getID())) {
480+
return set(Behavior::Fatal);
481+
}
482+
483+
// Re-map as appropriate
484+
switch (diagKind) {
485+
case DiagnosticKind::Error:
486+
return set(Behavior::Err);
487+
case DiagnosticKind::Warning:
488+
return set(ignoreAllWarnings ? Behavior::Ignore : Behavior::Warn);
489+
case DiagnosticKind::Note:
490+
return set(Behavior::Note);
491+
}
492+
}
493+
452494
void DiagnosticEngine::flushActiveDiagnostic() {
453495
assert(ActiveDiagnostic && "No active diagnostic to flush");
454496
if (TransactionCount == 0) {
@@ -467,34 +509,13 @@ void DiagnosticEngine::emitTentativeDiagnostics() {
467509
}
468510

469511
void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
512+
auto behavior = state.getBehavior(diagnostic);
513+
if (behavior == DiagnosticState::Behavior::Ignore)
514+
return;
515+
470516
const StoredDiagnosticInfo &StoredInfo
471517
= StoredDiagnosticInfos[(unsigned)diagnostic.getID()];
472518

473-
if (FatalState != FatalErrorState::None) {
474-
bool shouldIgnore = true;
475-
if (StoredInfo.Kind == DiagnosticKind::Note)
476-
shouldIgnore = (FatalState == FatalErrorState::Fatal);
477-
else
478-
FatalState = FatalErrorState::Fatal;
479-
480-
if (shouldIgnore && !ShowDiagnosticsAfterFatalError) {
481-
return;
482-
}
483-
}
484-
485-
// Check whether this is an error.
486-
switch (StoredInfo.Kind) {
487-
case DiagnosticKind::Error:
488-
HadAnyError = true;
489-
if (isDiagnosticFatal(diagnostic.getID()))
490-
FatalState = FatalErrorState::JustEmitted;
491-
break;
492-
493-
case DiagnosticKind::Note:
494-
case DiagnosticKind::Warning:
495-
break;
496-
}
497-
498519
// Figure out the source location.
499520
SourceLoc loc = diagnostic.getLoc();
500521
if (loc.isInvalid() && diagnostic.getDecl()) {

0 commit comments

Comments
 (0)