@@ -136,8 +136,8 @@ static constexpr EducationalNotes<LocalDiagID::NumDiags> _EducationalNotes = Edu
136136static constexpr auto educationalNotes = _EducationalNotes.value;
137137
138138DiagnosticState::DiagnosticState () {
139- // Initialize our per-diagnostic state to default
140- perDiagnosticBehavior .resize (LocalDiagID::NumDiags, Behavior::Unspecified );
139+ // Initialize our ignored diagnostics to default
140+ ignoredDiagnostics .resize (LocalDiagID::NumDiags);
141141}
142142
143143static CharSourceRange toCharSourceRange (SourceManager &SM, SourceRange SR) {
@@ -289,6 +289,12 @@ InFlightDiagnostic &InFlightDiagnostic::fixItExchange(SourceRange R1,
289289 return *this ;
290290}
291291
292+ InFlightDiagnostic &
293+ InFlightDiagnostic::limitBehavior (DiagnosticBehavior limit) {
294+ Engine->getActiveDiagnostic ().setBehaviorLimit (limit);
295+ return *this ;
296+ }
297+
292298void InFlightDiagnostic::flush () {
293299 if (!IsActive)
294300 return ;
@@ -779,26 +785,41 @@ void DiagnosticEngine::formatDiagnosticText(
779785 }
780786}
781787
782- static DiagnosticKind toDiagnosticKind (DiagnosticState::Behavior behavior) {
788+ static DiagnosticKind toDiagnosticKind (DiagnosticBehavior behavior) {
783789 switch (behavior) {
784- case DiagnosticState::Behavior ::Unspecified:
790+ case DiagnosticBehavior ::Unspecified:
785791 llvm_unreachable (" unspecified behavior" );
786- case DiagnosticState::Behavior ::Ignore:
792+ case DiagnosticBehavior ::Ignore:
787793 llvm_unreachable (" trying to map an ignored diagnostic" );
788- case DiagnosticState::Behavior ::Error:
789- case DiagnosticState::Behavior ::Fatal:
794+ case DiagnosticBehavior ::Error:
795+ case DiagnosticBehavior ::Fatal:
790796 return DiagnosticKind::Error;
791- case DiagnosticState::Behavior ::Note:
797+ case DiagnosticBehavior ::Note:
792798 return DiagnosticKind::Note;
793- case DiagnosticState::Behavior ::Warning:
799+ case DiagnosticBehavior ::Warning:
794800 return DiagnosticKind::Warning;
795- case DiagnosticState::Behavior ::Remark:
801+ case DiagnosticBehavior ::Remark:
796802 return DiagnosticKind::Remark;
797803 }
798804
799805 llvm_unreachable (" Unhandled DiagnosticKind in switch." );
800806}
801807
808+ static
809+ DiagnosticBehavior toDiagnosticBehavior (DiagnosticKind kind, bool isFatal) {
810+ switch (kind) {
811+ case DiagnosticKind::Note:
812+ return DiagnosticBehavior::Note;
813+ case DiagnosticKind::Error:
814+ return isFatal ? DiagnosticBehavior::Fatal : DiagnosticBehavior::Error;
815+ case DiagnosticKind::Warning:
816+ return DiagnosticBehavior::Warning;
817+ case DiagnosticKind::Remark:
818+ return DiagnosticBehavior::Remark;
819+ }
820+ llvm_unreachable (" Unhandled DiagnosticKind in switch." );
821+ }
822+
802823// A special option only for compiler writers that causes Diagnostics to assert
803824// when a failure diagnostic is emitted. Intended for use in the debugger.
804825llvm::cl::opt<bool > AssertOnError (" swift-diagnostics-assert-on-error" ,
@@ -808,72 +829,63 @@ llvm::cl::opt<bool> AssertOnError("swift-diagnostics-assert-on-error",
808829llvm::cl::opt<bool > AssertOnWarning (" swift-diagnostics-assert-on-warning" ,
809830 llvm::cl::init (false ));
810831
811- DiagnosticState::Behavior DiagnosticState::determineBehavior (DiagID id) {
812- auto set = [this ](DiagnosticState::Behavior lvl) {
813- if (lvl == Behavior::Fatal) {
814- fatalErrorOccurred = true ;
815- anyErrorOccurred = true ;
816- } else if (lvl == Behavior::Error) {
817- anyErrorOccurred = true ;
818- }
819-
820- assert ((!AssertOnError || !anyErrorOccurred) && " We emitted an error?!" );
821- assert ((!AssertOnWarning || (lvl != Behavior::Warning)) &&
822- " We emitted a warning?!" );
823- previousBehavior = lvl;
824- return lvl;
825- };
826-
832+ DiagnosticBehavior DiagnosticState::determineBehavior (const Diagnostic &diag) {
827833 // We determine how to handle a diagnostic based on the following rules
828- // 1) If current state dictates a certain behavior, follow that
829- // 2) If the user provided a behavior for this specific diagnostic, follow
830- // that
831- // 3) If the user provided a behavior for this diagnostic's kind, follow
832- // that
833- // 4) Otherwise remap the diagnostic kind
834-
835- auto diagInfo = storedDiagnosticInfos[(unsigned )id];
836- bool isNote = diagInfo.kind == DiagnosticKind::Note;
837-
838- // 1) If current state dictates a certain behavior, follow that
834+ // 1) Map the diagnostic to its "intended" behavior, applying the behavior
835+ // limit for this particular emission
836+ // 2) If current state dictates a certain behavior, follow that
837+ // 3) If the user ignored this specific diagnostic, follow that
838+ // 4) If the user substituted a different behavior for this behavior, apply
839+ // that change
840+ // 5) Update current state for use during the next diagnostic
841+
842+ // 1) Map the diagnostic to its "intended" behavior, applying the behavior
843+ // limit for this particular emission
844+ auto diagInfo = storedDiagnosticInfos[(unsigned )diag.getID ()];
845+ DiagnosticBehavior lvl =
846+ std::max (toDiagnosticBehavior (diagInfo.kind , diagInfo.isFatal ),
847+ diag.getBehaviorLimit ());
848+ assert (lvl != DiagnosticBehavior::Unspecified);
849+
850+ // 2) If current state dictates a certain behavior, follow that
839851
840852 // Notes relating to ignored diagnostics should also be ignored
841- if (previousBehavior == Behavior::Ignore && isNote)
842- return set (Behavior::Ignore);
853+ if (previousBehavior == DiagnosticBehavior::Ignore
854+ && lvl == DiagnosticBehavior::Note)
855+ lvl = DiagnosticBehavior::Ignore;
843856
844857 // Suppress diagnostics when in a fatal state, except for follow-on notes
845858 if (fatalErrorOccurred)
846- if (!showDiagnosticsAfterFatalError && !isNote )
847- return set (Behavior ::Ignore) ;
859+ if (!showDiagnosticsAfterFatalError && lvl != DiagnosticBehavior::Note )
860+ lvl = DiagnosticBehavior ::Ignore;
848861
849- // 2) If the user provided a behavior for this specific diagnostic, follow
850- // that
862+ // 3) If the user ignored this specific diagnostic, follow that
863+ if (ignoredDiagnostics[(unsigned )diag.getID ()])
864+ lvl = DiagnosticBehavior::Ignore;
851865
852- if (perDiagnosticBehavior[(unsigned )id] != Behavior::Unspecified)
853- return set (perDiagnosticBehavior[(unsigned )id]);
854-
855- // 3) If the user provided a behavior for this diagnostic's kind, follow
856- // that
857- if (diagInfo.kind == DiagnosticKind::Warning) {
858- if (suppressWarnings)
859- return set (Behavior::Ignore);
866+ // 4) If the user substituted a different behavior for this behavior, apply
867+ // that change
868+ if (lvl == DiagnosticBehavior::Warning) {
860869 if (warningsAsErrors)
861- return set (Behavior::Error);
870+ lvl = DiagnosticBehavior::Error;
871+ if (suppressWarnings)
872+ lvl = DiagnosticBehavior::Ignore;
862873 }
863874
864- // 4) Otherwise remap the diagnostic kind
865- switch (diagInfo.kind ) {
866- case DiagnosticKind::Note:
867- return set (Behavior::Note);
868- case DiagnosticKind::Error:
869- return set (diagInfo.isFatal ? Behavior::Fatal : Behavior::Error);
870- case DiagnosticKind::Warning:
871- return set (Behavior::Warning);
872- case DiagnosticKind::Remark:
873- return set (Behavior::Remark);
875+ // 5) Update current state for use during the next diagnostic
876+ if (lvl == DiagnosticBehavior::Fatal) {
877+ fatalErrorOccurred = true ;
878+ anyErrorOccurred = true ;
879+ } else if (lvl == DiagnosticBehavior::Error) {
880+ anyErrorOccurred = true ;
874881 }
875882
876- llvm_unreachable (" Unhandled DiagnosticKind in switch." );
883+ assert ((!AssertOnError || !anyErrorOccurred) && " We emitted an error?!" );
884+ assert ((!AssertOnWarning || (lvl != DiagnosticBehavior::Warning)) &&
885+ " We emitted a warning?!" );
886+
887+ previousBehavior = lvl;
888+ return lvl;
877889}
878890
879891void DiagnosticEngine::flushActiveDiagnostic () {
@@ -910,8 +922,8 @@ static AccessLevel getBufferAccessLevel(const Decl *decl) {
910922
911923Optional<DiagnosticInfo>
912924DiagnosticEngine::diagnosticInfoForDiagnostic (const Diagnostic &diagnostic) {
913- auto behavior = state.determineBehavior (diagnostic. getID () );
914- if (behavior == DiagnosticState::Behavior ::Ignore)
925+ auto behavior = state.determineBehavior (diagnostic);
926+ if (behavior == DiagnosticBehavior ::Ignore)
915927 return None;
916928
917929 // Figure out the source location.
0 commit comments