Skip to content

Commit 213b207

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 8a86e7f commit 213b207

32 files changed

+560
-248
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 {
@@ -1100,26 +1103,36 @@ BridgedSwiftNativeObjCRuntimeBaseAttr_createParsed(BridgedASTContext cContext,
11001103
swift::SourceRange range,
11011104
swift::Identifier name);
11021105

1103-
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedWarningGroupBehavior {
1104-
WarningGroupBehaviorError,
1105-
WarningGroupBehaviorWarning,
1106-
WarningGroupBehaviorIgnored,
1107-
};
1108-
11091106
SWIFT_NAME("BridgedWarnAttr.createParsed(_:atLoc:range:diagGroupName:behavior:reason:)")
11101107
BridgedWarnAttr
11111108
BridgedWarnAttr_createParsed(BridgedASTContext cContext,
11121109
swift::SourceLoc atLoc,
11131110
swift::SourceRange range,
11141111
swift::Identifier diagGroupName,
1115-
BridgedWarningGroupBehavior behavior,
1112+
swift::WarningGroupBehavior behavior,
11161113
BridgedStringRef reason);
11171114

11181115
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedNonSendableKind {
11191116
BridgedNonSendableKindSpecific,
11201117
BridgedNonSendableKindAssumed,
11211118
};
11221119

1120+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getGroupName(self:)")
1121+
BridgedStringRef BridgedWarningGroupBehaviorRule_getGroupName(BridgedWarningGroupBehaviorRule rule);
1122+
1123+
SWIFT_NAME("BridgedWarningGroupBehaviorRule.getBehavior(self:)")
1124+
swift::WarningGroupBehavior
1125+
BridgedWarningGroupBehaviorRule_getBehavior(BridgedWarningGroupBehaviorRule rule);
1126+
1127+
1128+
SWIFT_NAME("getDiagnosticGroupLinksCount()")
1129+
SwiftInt
1130+
BridgedDiagnosticGroupLinks_getCount();
1131+
1132+
SWIFT_NAME("getDiagnosticGroupLink(at:)")
1133+
std::pair<BridgedStringRef, BridgedStringRef>
1134+
BridgedDiagnosticGroupLinks_getLink(SwiftInt index);
1135+
11231136
SWIFT_NAME("BridgedNonSendableAttr.createParsed(_:atLoc:range:kind:)")
11241137
BridgedNonSendableAttr BridgedNonSendableAttr_createParsed(
11251138
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/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,10 @@ class ASTContext final {
14831483
/// the language options.
14841484
bool shouldPerformTypoCorrection();
14851485

1486+
/// Whether the specified SourceFile enables a given diagnostic group
1487+
/// either syntactically, or via command-line flags.
1488+
bool isDiagnosticGroupEnabled(SourceFile *sf, DiagGroupID groupID) const;
1489+
14861490
private:
14871491
friend class IntrinsicInfo;
14881492
/// Retrieve an LLVMContext that is used for scratch space for intrinsic lookup.

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"
@@ -3640,20 +3641,18 @@ class NonexhaustiveAttr : public DeclAttribute {
36403641

36413642
class WarnAttr : public DeclAttribute {
36423643
public:
3643-
enum class Behavior : uint8_t { Error, Warning, Ignored };
3644-
3645-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior,
3644+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior,
36463645
std::optional<StringRef> Reason, SourceLoc AtLoc, SourceRange Range,
36473646
bool Implicit)
36483647
: DeclAttribute(DeclAttrKind::Warn, AtLoc, Range, Implicit),
36493648
DiagnosticBehavior(Behavior), DiagnosticGroupID(DiagnosticGroupID),
36503649
Reason(Reason) {}
36513650

3652-
WarnAttr(DiagGroupID DiagnosticGroupID, Behavior Behavior, bool Implicit)
3651+
WarnAttr(DiagGroupID DiagnosticGroupID, WarningGroupBehavior Behavior, bool Implicit)
36533652
: WarnAttr(DiagnosticGroupID, Behavior, std::nullopt, SourceLoc(),
36543653
SourceRange(), Implicit) {}
36553654

3656-
Behavior DiagnosticBehavior;
3655+
WarningGroupBehavior DiagnosticBehavior;
36573656
DiagGroupID DiagnosticGroupID;
36583657
const std::optional<StringRef> Reason;
36593658

include/swift/AST/DiagnosticEngine.h

Lines changed: 59 additions & 45 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,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;

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)