2525#include " swift/Basic/PrintDiagnosticNamesMode.h"
2626#include " swift/Basic/Statistic.h"
2727#include " swift/Basic/Version.h"
28- #include " swift/Basic/WarningAsErrorRule .h"
28+ #include " swift/Basic/WarningGroupBehaviorRule .h"
2929#include " swift/Localization/LocalizationFormat.h"
3030#include " llvm/ADT/BitVector.h"
3131#include " llvm/ADT/StringRef.h"
@@ -612,6 +612,10 @@ namespace swift {
612612 ArrayRef<DiagnosticArgument> Args);
613613 };
614614
615+
616+ using WarningGroupBehaviorMap =
617+ std::unordered_map<swift::DiagGroupID, WarningGroupBehaviorRule>;
618+
615619 // / Class to track, map, and remap diagnostic severity and fatality
616620 // /
617621 class DiagnosticState {
@@ -628,13 +632,13 @@ namespace swift {
628632 // / Don't emit any remarks
629633 bool suppressRemarks = false ;
630634
631- // / A mapping from `DiagGroupID` identifiers to Boolean values indicating
632- // / whether warnings belonging to the respective diagnostic groups should be
633- // / escalated to errors.
634- llvm::BitVector warningsAsErrors;
635-
636- // / Track which diagnostic group (`DiagGroupID`) warnings should be ignored .
637- llvm::BitVector ignoredDiagnosticGroups ;
635+ // / A mapping from `DiagGroupID` identifiers to `WarningGroupBehaviorRule`
636+ // / values indicating how warnings belonging to the respective diagnostic groups
637+ // / should be emitted. While there is duplication between this data structure
638+ // / being a map keyed with `DiagGroupID` and containing a rule object which also
639+ // / contains a matching `DiagGroupID`, this significantly simplifies bridging
640+ // / values of this map to Swift clients .
641+ WarningGroupBehaviorMap warningGroupBehaviorMap ;
638642
639643 // / For compiler-internal purposes only, track which diagnostics should
640644 // / be ignored completely. For example, this is used by LLDB to
@@ -657,7 +661,8 @@ namespace swift {
657661
658662 // / Figure out the Behavior for the given diagnostic, taking current
659663 // / state such as fatality into account.
660- DiagnosticBehavior determineBehavior (const Diagnostic &diag) const ;
664+ DiagnosticBehavior determineBehavior (const Diagnostic &diag,
665+ SourceManager &sourceMgr) const ;
661666
662667 // / Updates the diagnostic state for a diagnostic to emit.
663668 void updateFor (DiagnosticBehavior behavior);
@@ -684,45 +689,37 @@ namespace swift {
684689 void setSuppressRemarks (bool val) { suppressRemarks = val; }
685690 bool getSuppressRemarks () const { return suppressRemarks; }
686691
687- // / Sets whether warnings belonging to the diagnostic group identified by
688- // / `id` should be escalated to errors.
689- void setWarningsAsErrorsForDiagGroupID (DiagGroupID id, bool value) {
690- warningsAsErrors[(unsigned )id] = value;
692+ // / Configure the command-line warning group handling
693+ // / rules (`-Werrr`,`-Wwarning`,`-warnings-as-errors`)
694+ void setWarningGroupControlRules (
695+ const llvm::SmallVector<WarningGroupBehaviorRule, 4 > &rules);
696+
697+ // / Add an individual command-line warning group behavior
698+ void addWarningGroupControl (const DiagGroupID &groupID,
699+ WarningGroupBehavior behavior) {
700+ warningGroupBehaviorMap.insert_or_assign (
701+ groupID, WarningGroupBehaviorRule (behavior, groupID));
691702 }
692703
693- // / Returns a Boolean value indicating whether warnings belonging to the
694- // / diagnostic group identified by `id` should be escalated to errors.
695- bool getWarningsAsErrorsForDiagGroupID (DiagGroupID id) const {
696- return warningsAsErrors[(unsigned )id];
704+ const WarningGroupBehaviorMap&
705+ getWarningGroupBehaviorControlMap () const {
706+ return warningGroupBehaviorMap;
697707 }
698708
699- // / Whether all warnings should be upgraded to errors or not.
700- void setAllWarningsAsErrors (bool value) {
701- // This works as intended because every diagnostic belongs to either a
702- // custom group or the top-level `DiagGroupID::no_group`, which is also
703- // a group.
704- if (value) {
705- warningsAsErrors.set ();
706- } else {
707- warningsAsErrors.reset ();
708- }
709+ const std::vector<const WarningGroupBehaviorRule*>
710+ getWarningGroupBehaviorControlRefArray () const {
711+ std::vector<const WarningGroupBehaviorRule*> ruleRefArray;
712+ ruleRefArray.reserve (warningGroupBehaviorMap.size ());
713+ for (const auto &rule: warningGroupBehaviorMap)
714+ ruleRefArray.push_back (&rule.second );
715+ return ruleRefArray;
709716 }
710717
711718 void resetHadAnyError () {
712719 anyErrorOccurred = false ;
713720 fatalErrorOccurred = false ;
714721 }
715722
716- // / Set whether a diagnostic group should be ignored.
717- void setIgnoredDiagnosticGroup (DiagGroupID id, bool ignored) {
718- ignoredDiagnosticGroups[(unsigned )id] = ignored;
719- }
720-
721- // / Query whether a specific diagnostic group is ignored.
722- bool isIgnoredDiagnosticGroup (DiagGroupID id) const {
723- return ignoredDiagnosticGroups[(unsigned )id];
724- }
725-
726723 // / Set a specific diagnostic to be ignored by the compiler.
727724 void compilerInternalIgnoreDiagnostic (DiagID id) {
728725 compilerIgnoredDiagnostics[(unsigned )id] = true ;
@@ -738,11 +735,10 @@ namespace swift {
738735 std::swap (suppressWarnings, other.suppressWarnings );
739736 std::swap (suppressNotes, other.suppressNotes );
740737 std::swap (suppressRemarks, other.suppressRemarks );
741- std::swap (warningsAsErrors , other.warningsAsErrors );
738+ std::swap (warningGroupBehaviorMap , other.warningGroupBehaviorMap );
742739 std::swap (fatalErrorOccurred, other.fatalErrorOccurred );
743740 std::swap (anyErrorOccurred, other.anyErrorOccurred );
744741 std::swap (previousBehavior, other.previousBehavior );
745- std::swap (ignoredDiagnosticGroups, other.ignoredDiagnosticGroups );
746742 }
747743
748744 private:
@@ -752,6 +748,13 @@ namespace swift {
752748
753749 DiagnosticState (DiagnosticState &&) = default ;
754750 DiagnosticState &operator =(DiagnosticState &&) = default ;
751+
752+ // / If this diagnostic is a warning belonging to a diagnostic group,
753+ // / figure out if there is a source-level (`@warn`) control for this group
754+ // / for this diagnostic's source location.
755+ std::optional<DiagnosticBehavior>
756+ determineUserControlledWarningBehavior (const Diagnostic &diag,
757+ SourceManager &sourceMgr) const ;
755758 };
756759
757760 // / A lightweight reference to a diagnostic that's been fully applied to
@@ -951,7 +954,20 @@ namespace swift {
951954 // / Rules are applied in order they appear in the vector.
952955 // / In case the vector contains rules affecting the same diagnostic ID
953956 // / the last rule wins.
954- void setWarningsAsErrorsRules (const std::vector<WarningAsErrorRule> &rules);
957+ void setWarningGroupControlRules (
958+ const llvm::SmallVector<WarningGroupBehaviorRule, 4 > &rules) {
959+ state.setWarningGroupControlRules (rules);
960+ }
961+
962+ const WarningGroupBehaviorMap&
963+ getWarningGroupBehaviorControlMap () const {
964+ return state.getWarningGroupBehaviorControlMap ();
965+ }
966+
967+ const std::vector<const WarningGroupBehaviorRule*>
968+ getWarningGroupBehaviorControlRefArray () const {
969+ return state.getWarningGroupBehaviorControlRefArray ();
970+ }
955971
956972 // / Whether to print diagnostic names after their messages
957973 void setPrintDiagnosticNamesMode (PrintDiagnosticNamesMode val) {
@@ -982,13 +998,9 @@ namespace swift {
982998 localization = diag::LocalizationProducer::producerFor (locale, path);
983999 }
9841000
985- bool isIgnoredDiagnosticGroup (DiagGroupID id) const {
986- return state.isIgnoredDiagnosticGroup (id);
987- }
988-
989- bool isIgnoredDiagnosticGroupTree (DiagGroupID id) const {
990- return state.isIgnoredDiagnosticGroupTree (id);
991- }
1001+ // / Whether the specified SourceFile enables a given diagnostic group
1002+ // / either syntactically, or via command-line flags.
1003+ bool isDiagnosticGroupEnabled (SourceFile *sf, DiagGroupID groupID) const ;
9921004
9931005 void ignoreDiagnostic (DiagID id) {
9941006 state.compilerInternalIgnoreDiagnostic (id);
@@ -1366,7 +1378,8 @@ namespace swift {
13661378 Engine.TentativeDiagnostics .end ());
13671379
13681380 for (auto &diagnostic : diagnostics) {
1369- auto behavior = Engine.state .determineBehavior (diagnostic.Diag );
1381+ auto behavior = Engine.state .determineBehavior (diagnostic.Diag ,
1382+ Engine.SourceMgr );
13701383 if (behavior == DiagnosticBehavior::Fatal ||
13711384 behavior == DiagnosticBehavior::Error)
13721385 return true ;
0 commit comments