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,38 @@ 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.emplace (groupID,
701+ WarningGroupBehaviorRule (behavior,
702+ groupID));
691703 }
692704
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];
705+ const WarningGroupBehaviorMap&
706+ getWarningGroupBehaviorControlMap () const {
707+ return warningGroupBehaviorMap;
697708 }
698709
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- }
710+ const std::vector<const WarningGroupBehaviorRule*>
711+ getWarningGroupBehaviorControlRefArray () const {
712+ std::vector<const WarningGroupBehaviorRule*> ruleRefArray;
713+ ruleRefArray.reserve (warningGroupBehaviorMap.size ());
714+ for (const auto &rule: warningGroupBehaviorMap)
715+ ruleRefArray.push_back (&rule.second );
716+ return ruleRefArray;
709717 }
710718
711719 void resetHadAnyError () {
712720 anyErrorOccurred = false ;
713721 fatalErrorOccurred = false ;
714722 }
715723
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-
726724 // / Set a specific diagnostic to be ignored by the compiler.
727725 void compilerInternalIgnoreDiagnostic (DiagID id) {
728726 compilerIgnoredDiagnostics[(unsigned )id] = true ;
@@ -738,11 +736,10 @@ namespace swift {
738736 std::swap (suppressWarnings, other.suppressWarnings );
739737 std::swap (suppressNotes, other.suppressNotes );
740738 std::swap (suppressRemarks, other.suppressRemarks );
741- std::swap (warningsAsErrors , other.warningsAsErrors );
739+ std::swap (warningGroupBehaviorMap , other.warningGroupBehaviorMap );
742740 std::swap (fatalErrorOccurred, other.fatalErrorOccurred );
743741 std::swap (anyErrorOccurred, other.anyErrorOccurred );
744742 std::swap (previousBehavior, other.previousBehavior );
745- std::swap (ignoredDiagnosticGroups, other.ignoredDiagnosticGroups );
746743 }
747744
748745 private:
@@ -752,6 +749,13 @@ namespace swift {
752749
753750 DiagnosticState (DiagnosticState &&) = default ;
754751 DiagnosticState &operator =(DiagnosticState &&) = default ;
752+
753+ // / If this diagnostic is a warning belonging to a diagnostic group,
754+ // / figure out if there is a source-level (`@warn`) control for this group
755+ // / for this diagnostic's source location.
756+ std::optional<DiagnosticBehavior>
757+ determineUserControlledWarningBehavior (const Diagnostic &diag,
758+ SourceManager &sourceMgr) const ;
755759 };
756760
757761 // / A lightweight reference to a diagnostic that's been fully applied to
@@ -951,7 +955,20 @@ namespace swift {
951955 // / Rules are applied in order they appear in the vector.
952956 // / In case the vector contains rules affecting the same diagnostic ID
953957 // / the last rule wins.
954- void setWarningsAsErrorsRules (const std::vector<WarningAsErrorRule> &rules);
958+ void setWarningGroupControlRules (
959+ const llvm::SmallVector<WarningGroupBehaviorRule, 4 > &rules) {
960+ state.setWarningGroupControlRules (rules);
961+ }
962+
963+ const WarningGroupBehaviorMap&
964+ getWarningGroupBehaviorControlMap () const {
965+ return state.getWarningGroupBehaviorControlMap ();
966+ }
967+
968+ const std::vector<const WarningGroupBehaviorRule*>
969+ getWarningGroupBehaviorControlRefArray () const {
970+ return state.getWarningGroupBehaviorControlRefArray ();
971+ }
955972
956973 // / Whether to print diagnostic names after their messages
957974 void setPrintDiagnosticNamesMode (PrintDiagnosticNamesMode val) {
@@ -982,10 +999,6 @@ namespace swift {
982999 localization = diag::LocalizationProducer::producerFor (locale, path);
9831000 }
9841001
985- bool isIgnoredDiagnosticGroup (DiagGroupID id) const {
986- return state.isIgnoredDiagnosticGroup (id);
987- }
988-
9891002 bool isIgnoredDiagnosticGroupTree (DiagGroupID id) const {
9901003 return state.isIgnoredDiagnosticGroupTree (id);
9911004 }
@@ -1366,7 +1379,8 @@ namespace swift {
13661379 Engine.TentativeDiagnostics .end ());
13671380
13681381 for (auto &diagnostic : diagnostics) {
1369- auto behavior = Engine.state .determineBehavior (diagnostic.Diag );
1382+ auto behavior = Engine.state .determineBehavior (diagnostic.Diag ,
1383+ Engine.SourceMgr );
13701384 if (behavior == DiagnosticBehavior::Fatal ||
13711385 behavior == DiagnosticBehavior::Error)
13721386 return true ;
0 commit comments