Skip to content

Commit 40beea2

Browse files
committed
Implement support for unified warning group behavior queries per-diagnostic
Unified across module-wide configuration flags (`-Wwarning`, `-Werror`, etc.) and syntactic configuration attribute `@warn`.
1 parent 199457e commit 40beea2

33 files changed

+697
-258
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@
2727
#include "swift/AST/LayoutConstraintKind.h"
2828
#include "swift/AST/PlatformKind.h"
2929
#include "swift/Basic/BasicBridging.h"
30+
#include "swift/Basic/WarningGroupBehavior.h"
3031

3132
#ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE
3233
#include "swift/AST/Attr.h"
3334
#include "swift/AST/Decl.h"
3435
#endif
3536

37+
#include <utility>
38+
3639
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
3740

3841
namespace llvm {
@@ -1111,26 +1114,36 @@ BridgedSwiftNativeObjCRuntimeBaseAttr_createParsed(BridgedASTContext cContext,
11111114
swift::SourceRange range,
11121115
swift::Identifier name);
11131116

1114-
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedWarningGroupBehavior {
1115-
WarningGroupBehaviorError,
1116-
WarningGroupBehaviorWarning,
1117-
WarningGroupBehaviorIgnored,
1118-
};
1119-
11201117
SWIFT_NAME("BridgedWarnAttr.createParsed(_:atLoc:range:diagGroupName:behavior:reason:)")
11211118
BridgedWarnAttr
11221119
BridgedWarnAttr_createParsed(BridgedASTContext cContext,
11231120
swift::SourceLoc atLoc,
11241121
swift::SourceRange range,
11251122
swift::Identifier diagGroupName,
1126-
BridgedWarningGroupBehavior behavior,
1123+
swift::WarningGroupBehavior behavior,
11271124
BridgedStringRef reason);
11281125

11291126
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedNonSendableKind {
11301127
BridgedNonSendableKindSpecific,
11311128
BridgedNonSendableKindAssumed,
11321129
};
11331130

1131+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getGroupName(self:)")
1132+
BridgedStringRef BridgedWarningGroupBehaviorRule_getGroupName(BridgedWarningGroupBehaviorRule rule);
1133+
1134+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getBehavior(self:)")
1135+
swift::WarningGroupBehavior
1136+
BridgedWarningGroupBehaviorRule_getBehavior(BridgedWarningGroupBehaviorRule rule);
1137+
1138+
1139+
SWIFT_NAME("getDiagnosticGroupLinksCount()")
1140+
SwiftInt
1141+
BridgedDiagnosticGroupLinks_getCount();
1142+
1143+
SWIFT_NAME("getDiagnosticGroupLink(at:)")
1144+
std::pair<BridgedStringRef, BridgedStringRef>
1145+
BridgedDiagnosticGroupLinks_getLink(SwiftInt index);
1146+
11341147
SWIFT_NAME("BridgedNonSendableAttr.createParsed(_:atLoc:range:kind:)")
11351148
BridgedNonSendableAttr BridgedNonSendableAttr_createParsed(
11361149
BridgedASTContext cContext, swift::SourceLoc atLoc,

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
114114
AST_BRIDGING_WRAPPER_NULLABLE(ArgumentList)
115115
AST_BRIDGING_WRAPPER_NULLABLE(AvailabilitySpec)
116116
AST_BRIDGING_WRAPPER_CONST_NONNULL(AvailabilityMacroMap)
117+
AST_BRIDGING_WRAPPER_NULLABLE(WarningGroupBehaviorRule)
117118
AST_BRIDGING_WRAPPER_NONNULL(PoundAvailableInfo)
118119
AST_BRIDGING_WRAPPER_NONNULL(LifetimeEntry)
119120

include/swift/AST/Attr.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "swift/Basic/SourceLoc.h"
4444
#include "swift/Basic/UUID.h"
4545
#include "swift/Basic/Version.h"
46+
#include "swift/Basic/WarningGroupBehavior.h"
4647
#include "llvm/ADT/DenseMapInfo.h"
4748
#include "llvm/ADT/SmallVector.h"
4849
#include "llvm/ADT/StringRef.h"
@@ -3681,20 +3682,18 @@ class NonexhaustiveAttr : public DeclAttribute {
36813682

36823683
class WarnAttr : public DeclAttribute {
36833684
public:
3684-
enum class Behavior : uint8_t { Error, Warning, Ignored };
3685-
3686-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior,
3685+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior,
36873686
std::optional<StringRef> Reason, SourceLoc AtLoc, SourceRange Range,
36883687
bool Implicit)
36893688
: DeclAttribute(DeclAttrKind::Warn, AtLoc, Range, Implicit),
36903689
DiagnosticBehavior(Behavior), DiagnosticGroupID(DiagnosticGroupID),
36913690
Reason(Reason) {}
36923691

3693-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior, bool Implicit)
3692+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior, bool Implicit)
36943693
: WarnAttr(DiagnosticGroupID, Behavior, std::nullopt, SourceLoc(),
36953694
SourceRange(), Implicit) {}
36963695

3697-
Behavior DiagnosticBehavior;
3696+
WarningGroupBehavior DiagnosticBehavior;
36983697
DiagGroupID DiagnosticGroupID;
36993698
const std::optional<StringRef> Reason;
37003699

include/swift/AST/DiagnosticEngine.h

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
#include "swift/AST/DeclNameLoc.h"
2222
#include "swift/AST/DiagnosticArgument.h"
2323
#include "swift/AST/DiagnosticConsumer.h"
24+
#include "swift/AST/DiagnosticGroups.h"
2425
#include "swift/AST/TypeLoc.h"
2526
#include "swift/Basic/PrintDiagnosticNamesMode.h"
2627
#include "swift/Basic/Statistic.h"
2728
#include "swift/Basic/Version.h"
28-
#include "swift/Basic/WarningAsErrorRule.h"
29+
#include "swift/Basic/WarningGroupBehaviorRule.h"
2930
#include "swift/Localization/LocalizationFormat.h"
3031
#include "llvm/ADT/BitVector.h"
32+
#include "llvm/ADT/MapVector.h"
3133
#include "llvm/ADT/StringRef.h"
3234
#include "llvm/ADT/StringSet.h"
3335
#include "llvm/Support/Allocator.h"
@@ -612,6 +614,10 @@ namespace swift {
612614
ArrayRef<DiagnosticArgument> Args);
613615
};
614616

617+
618+
using WarningGroupBehaviorMap =
619+
llvm::MapVector<swift::DiagGroupID, WarningGroupBehaviorRule>;
620+
615621
/// Class to track, map, and remap diagnostic severity and fatality
616622
///
617623
class DiagnosticState {
@@ -628,13 +634,13 @@ namespace swift {
628634
/// Don't emit any remarks
629635
bool suppressRemarks = false;
630636

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;
637+
/// A mapping from `DiagGroupID` identifiers to `WarningGroupBehaviorRule`
638+
/// values indicating how warnings belonging to the respective diagnostic groups
639+
/// should be emitted. While there is duplication between this data structure
640+
/// being a map keyed with `DiagGroupID` and containing a rule object which also
641+
/// contains a matching `DiagGroupID`, this significantly simplifies bridging
642+
/// values of this map to Swift clients.
643+
WarningGroupBehaviorMap warningGroupBehaviorMap;
638644

639645
/// For compiler-internal purposes only, track which diagnostics should
640646
/// be ignored completely. For example, this is used by LLDB to
@@ -657,7 +663,8 @@ namespace swift {
657663

658664
/// Figure out the Behavior for the given diagnostic, taking current
659665
/// state such as fatality into account.
660-
DiagnosticBehavior determineBehavior(const Diagnostic &diag) const;
666+
DiagnosticBehavior determineBehavior(const Diagnostic &diag,
667+
SourceManager &sourceMgr) const;
661668

662669
/// Updates the diagnostic state for a diagnostic to emit.
663670
void updateFor(DiagnosticBehavior behavior);
@@ -684,45 +691,37 @@ namespace swift {
684691
void setSuppressRemarks(bool val) { suppressRemarks = val; }
685692
bool getSuppressRemarks() const { return suppressRemarks; }
686693

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;
694+
/// Configure the command-line warning group handling
695+
/// rules (`-Werrr`,`-Wwarning`,`-warnings-as-errors`)
696+
void setWarningGroupControlRules(
697+
const llvm::SmallVector<WarningGroupBehaviorRule, 4> &rules);
698+
699+
/// Add an individual command-line warning group behavior
700+
void addWarningGroupControl(const DiagGroupID &groupID,
701+
WarningGroupBehavior behavior) {
702+
warningGroupBehaviorMap.insert_or_assign(
703+
groupID, WarningGroupBehaviorRule(behavior, groupID));
691704
}
692705

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];
706+
const WarningGroupBehaviorMap&
707+
getWarningGroupBehaviorControlMap() const {
708+
return warningGroupBehaviorMap;
697709
}
698710

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-
}
711+
const std::vector<const WarningGroupBehaviorRule*>
712+
getWarningGroupBehaviorControlRefArray() const {
713+
std::vector<const WarningGroupBehaviorRule*> ruleRefArray;
714+
ruleRefArray.reserve(warningGroupBehaviorMap.size());
715+
for (const auto &rule: warningGroupBehaviorMap)
716+
ruleRefArray.push_back(&rule.second);
717+
return ruleRefArray;
709718
}
710719

711720
void resetHadAnyError() {
712721
anyErrorOccurred = false;
713722
fatalErrorOccurred = false;
714723
}
715724

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-
726725
/// Set a specific diagnostic to be ignored by the compiler.
727726
void compilerInternalIgnoreDiagnostic(DiagID id) {
728727
compilerIgnoredDiagnostics[(unsigned)id] = true;
@@ -738,11 +737,10 @@ namespace swift {
738737
std::swap(suppressWarnings, other.suppressWarnings);
739738
std::swap(suppressNotes, other.suppressNotes);
740739
std::swap(suppressRemarks, other.suppressRemarks);
741-
std::swap(warningsAsErrors, other.warningsAsErrors);
740+
std::swap(warningGroupBehaviorMap, other.warningGroupBehaviorMap);
742741
std::swap(fatalErrorOccurred, other.fatalErrorOccurred);
743742
std::swap(anyErrorOccurred, other.anyErrorOccurred);
744743
std::swap(previousBehavior, other.previousBehavior);
745-
std::swap(ignoredDiagnosticGroups, other.ignoredDiagnosticGroups);
746744
}
747745

748746
private:
@@ -752,6 +750,13 @@ namespace swift {
752750

753751
DiagnosticState(DiagnosticState &&) = default;
754752
DiagnosticState &operator=(DiagnosticState &&) = default;
753+
754+
/// If this diagnostic is a warning belonging to a diagnostic group,
755+
/// figure out if there is a source-level (`@warn`) control for this group
756+
/// for this diagnostic's source location.
757+
std::optional<DiagnosticBehavior>
758+
determineUserControlledWarningBehavior(const Diagnostic &diag,
759+
SourceManager &sourceMgr) const;
755760
};
756761

757762
/// A lightweight reference to a diagnostic that's been fully applied to
@@ -951,7 +956,20 @@ namespace swift {
951956
/// Rules are applied in order they appear in the vector.
952957
/// In case the vector contains rules affecting the same diagnostic ID
953958
/// the last rule wins.
954-
void setWarningsAsErrorsRules(const std::vector<WarningAsErrorRule> &rules);
959+
void setWarningGroupControlRules(
960+
const llvm::SmallVector<WarningGroupBehaviorRule, 4> &rules) {
961+
state.setWarningGroupControlRules(rules);
962+
}
963+
964+
const WarningGroupBehaviorMap&
965+
getWarningGroupBehaviorControlMap() const {
966+
return state.getWarningGroupBehaviorControlMap();
967+
}
968+
969+
const std::vector<const WarningGroupBehaviorRule*>
970+
getWarningGroupBehaviorControlRefArray() const {
971+
return state.getWarningGroupBehaviorControlRefArray();
972+
}
955973

956974
/// Whether to print diagnostic names after their messages
957975
void setPrintDiagnosticNamesMode(PrintDiagnosticNamesMode val) {
@@ -982,13 +1000,9 @@ namespace swift {
9821000
localization = diag::LocalizationProducer::producerFor(locale, path);
9831001
}
9841002

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-
}
1003+
/// Whether the specified SourceFile enables a given diagnostic group
1004+
/// either syntactically, or via command-line flags.
1005+
bool isDiagnosticGroupEnabled(SourceFile *sf, DiagGroupID groupID) const;
9921006

9931007
void ignoreDiagnostic(DiagID id) {
9941008
state.compilerInternalIgnoreDiagnostic(id);
@@ -1366,7 +1380,8 @@ namespace swift {
13661380
Engine.TentativeDiagnostics.end());
13671381

13681382
for (auto &diagnostic : diagnostics) {
1369-
auto behavior = Engine.state.determineBehavior(diagnostic.Diag);
1383+
auto behavior = Engine.state.determineBehavior(diagnostic.Diag,
1384+
Engine.SourceMgr);
13701385
if (behavior == DiagnosticBehavior::Fatal ||
13711386
behavior == DiagnosticBehavior::Error)
13721387
return true;

include/swift/Basic/DiagnosticOptions.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#define SWIFT_BASIC_DIAGNOSTICOPTIONS_H
1515

1616
#include "swift/Basic/PrintDiagnosticNamesMode.h"
17-
#include "swift/Basic/WarningAsErrorRule.h"
17+
#include "swift/Basic/WarningGroupBehaviorRule.h"
1818
#include "llvm/ADT/Hashing.h"
1919
#include <vector>
2020

@@ -76,7 +76,7 @@ class DiagnosticOptions {
7676
bool SuppressRemarks = false;
7777

7878
/// Rules for escalating warnings to errors
79-
std::vector<WarningAsErrorRule> WarningsAsErrorsRules;
79+
llvm::SmallVector<WarningGroupBehaviorRule, 4> WarningGroupControlRules;
8080

8181
/// When printing diagnostics, include either the diagnostic name
8282
/// (diag::whatever) at the end or the associated diagnostic group.

include/swift/Basic/WarningAsErrorRule.h

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)