Skip to content

Commit 693aeae

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 5fcd226 commit 693aeae

33 files changed

+688
-257
lines changed

include/swift/AST/ASTBridging.h

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

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

36+
#include <utility>
37+
3538
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
3639

3740
namespace llvm {
@@ -1104,26 +1107,36 @@ BridgedSwiftNativeObjCRuntimeBaseAttr_createParsed(BridgedASTContext cContext,
11041107
swift::SourceRange range,
11051108
swift::Identifier name);
11061109

1107-
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedWarningGroupBehavior {
1108-
WarningGroupBehaviorError,
1109-
WarningGroupBehaviorWarning,
1110-
WarningGroupBehaviorIgnored,
1111-
};
1112-
11131110
SWIFT_NAME("BridgedWarnAttr.createParsed(_:atLoc:range:diagGroupName:behavior:reason:)")
11141111
BridgedWarnAttr
11151112
BridgedWarnAttr_createParsed(BridgedASTContext cContext,
11161113
swift::SourceLoc atLoc,
11171114
swift::SourceRange range,
11181115
swift::Identifier diagGroupName,
1119-
BridgedWarningGroupBehavior behavior,
1116+
swift::WarningGroupBehavior behavior,
11201117
BridgedStringRef reason);
11211118

11221119
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedNonSendableKind {
11231120
BridgedNonSendableKindSpecific,
11241121
BridgedNonSendableKindAssumed,
11251122
};
11261123

1124+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getGroupName(self:)")
1125+
BridgedStringRef BridgedWarningGroupBehaviorRule_getGroupName(BridgedWarningGroupBehaviorRule rule);
1126+
1127+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getBehavior(self:)")
1128+
swift::WarningGroupBehavior
1129+
BridgedWarningGroupBehaviorRule_getBehavior(BridgedWarningGroupBehaviorRule rule);
1130+
1131+
1132+
SWIFT_NAME("getDiagnosticGroupLinksCount()")
1133+
SwiftInt
1134+
BridgedDiagnosticGroupLinks_getCount();
1135+
1136+
SWIFT_NAME("getDiagnosticGroupLink(at:)")
1137+
std::pair<BridgedStringRef, BridgedStringRef>
1138+
BridgedDiagnosticGroupLinks_getLink(SwiftInt index);
1139+
11271140
SWIFT_NAME("BridgedNonSendableAttr.createParsed(_:atLoc:range:kind:)")
11281141
BridgedNonSendableAttr BridgedNonSendableAttr_createParsed(
11291142
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
@@ -42,6 +42,7 @@
4242
#include "swift/Basic/SourceLoc.h"
4343
#include "swift/Basic/UUID.h"
4444
#include "swift/Basic/Version.h"
45+
#include "swift/Basic/WarningGroupBehavior.h"
4546
#include "llvm/ADT/DenseMapInfo.h"
4647
#include "llvm/ADT/SmallVector.h"
4748
#include "llvm/ADT/StringRef.h"
@@ -3644,20 +3645,18 @@ class NonexhaustiveAttr : public DeclAttribute {
36443645

36453646
class WarnAttr : public DeclAttribute {
36463647
public:
3647-
enum class Behavior : uint8_t { Error, Warning, Ignored };
3648-
3649-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior,
3648+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior,
36503649
std::optional<StringRef> Reason, SourceLoc AtLoc, SourceRange Range,
36513650
bool Implicit)
36523651
: DeclAttribute(DeclAttrKind::Warn, AtLoc, Range, Implicit),
36533652
DiagnosticBehavior(Behavior), DiagnosticGroupID(DiagnosticGroupID),
36543653
Reason(Reason) {}
36553654

3656-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior, bool Implicit)
3655+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior, bool Implicit)
36573656
: WarnAttr(DiagnosticGroupID, Behavior, std::nullopt, SourceLoc(),
36583657
SourceRange(), Implicit) {}
36593658

3660-
Behavior DiagnosticBehavior;
3659+
WarningGroupBehavior DiagnosticBehavior;
36613660
DiagGroupID DiagnosticGroupID;
36623661
const std::optional<StringRef> Reason;
36633662

include/swift/AST/DiagnosticEngine.h

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
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;

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)