mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85098 from artemcm/DefaultIgnoreDiagnosticGroups
[Diagnostics] Replace diagnostics' `DefaultIgnore` option with a corresponding option on diagnostic groups
This commit is contained in:
@@ -28,10 +28,11 @@
|
||||
// Declares a diagnostic group.
|
||||
// Parameters:
|
||||
// Name - group name as it appears in DiagGroupID enum and DiagGroupInfo.name
|
||||
// Option - attribute applying to members of this diagnostic group
|
||||
// DocsFile - file with a human readable description for the group located in
|
||||
// userdocs/diagnostic_groups
|
||||
#ifndef GROUP
|
||||
#define GROUP(Name, DocsFile)
|
||||
#define GROUP(Name, Option, DocsFile)
|
||||
#endif
|
||||
|
||||
// GROUP_LINK macro:
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace swift {
|
||||
/// this enumeration type that uniquely identifies it.
|
||||
enum class DiagID : uint32_t;
|
||||
|
||||
enum class DiagGroupID : uint16_t;
|
||||
enum class DiagGroupID : uint32_t;
|
||||
|
||||
/// Describes a diagnostic along with its argument types.
|
||||
///
|
||||
@@ -633,6 +633,14 @@ namespace swift {
|
||||
/// escalated to errors.
|
||||
llvm::BitVector warningsAsErrors;
|
||||
|
||||
/// Track which diagnostic group (`DiagGroupID`) warnings should be ignored.
|
||||
llvm::BitVector ignoredDiagnosticGroups;
|
||||
|
||||
/// For compiler-internal purposes only, track which diagnostics should
|
||||
/// be ignored completely. For example, this is used by LLDB to
|
||||
/// suppress certain errors in expression evaluation.
|
||||
llvm::BitVector compilerIgnoredDiagnostics;
|
||||
|
||||
/// Whether a fatal error has occurred
|
||||
bool fatalErrorOccurred = false;
|
||||
|
||||
@@ -642,9 +650,6 @@ namespace swift {
|
||||
/// Track the previous emitted Behavior, useful for notes
|
||||
DiagnosticBehavior previousBehavior = DiagnosticBehavior::Unspecified;
|
||||
|
||||
/// Track which diagnostics should be ignored.
|
||||
llvm::BitVector ignoredDiagnostics;
|
||||
|
||||
friend class DiagnosticStateRAII;
|
||||
|
||||
public:
|
||||
@@ -708,17 +713,28 @@ namespace swift {
|
||||
fatalErrorOccurred = false;
|
||||
}
|
||||
|
||||
/// Set whether a diagnostic should be ignored.
|
||||
void setIgnoredDiagnostic(DiagID id, bool ignored) {
|
||||
ignoredDiagnostics[(unsigned)id] = ignored;
|
||||
/// Set whether a diagnostic group should be ignored.
|
||||
void setIgnoredDiagnosticGroup(DiagGroupID id, bool ignored) {
|
||||
ignoredDiagnosticGroups[(unsigned)id] = ignored;
|
||||
}
|
||||
|
||||
bool isIgnoredDiagnostic(DiagID id) const {
|
||||
return ignoredDiagnostics[(unsigned)id];
|
||||
/// Query whether a specific diagnostic group is ignored.
|
||||
bool isIgnoredDiagnosticGroup(DiagGroupID id) const {
|
||||
return ignoredDiagnosticGroups[(unsigned)id];
|
||||
}
|
||||
|
||||
/// Set a specific diagnostic to be ignored by the compiler.
|
||||
void compilerInternalIgnoreDiagnostic(DiagID id) {
|
||||
compilerIgnoredDiagnostics[(unsigned)id] = true;
|
||||
}
|
||||
|
||||
/// Query whether a specific diagnostic group and *all*
|
||||
/// of its subgroups are ignored.
|
||||
bool isIgnoredDiagnosticGroupTree(DiagGroupID id) const;
|
||||
|
||||
void swap(DiagnosticState &other) {
|
||||
std::swap(showDiagnosticsAfterFatalError, other.showDiagnosticsAfterFatalError);
|
||||
std::swap(showDiagnosticsAfterFatalError,
|
||||
other.showDiagnosticsAfterFatalError);
|
||||
std::swap(suppressWarnings, other.suppressWarnings);
|
||||
std::swap(suppressNotes, other.suppressNotes);
|
||||
std::swap(suppressRemarks, other.suppressRemarks);
|
||||
@@ -726,7 +742,7 @@ namespace swift {
|
||||
std::swap(fatalErrorOccurred, other.fatalErrorOccurred);
|
||||
std::swap(anyErrorOccurred, other.anyErrorOccurred);
|
||||
std::swap(previousBehavior, other.previousBehavior);
|
||||
std::swap(ignoredDiagnostics, other.ignoredDiagnostics);
|
||||
std::swap(ignoredDiagnosticGroups, other.ignoredDiagnosticGroups);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -966,12 +982,16 @@ namespace swift {
|
||||
localization = diag::LocalizationProducer::producerFor(locale, path);
|
||||
}
|
||||
|
||||
void ignoreDiagnostic(DiagID id) {
|
||||
state.setIgnoredDiagnostic(id, true);
|
||||
bool isIgnoredDiagnosticGroup(DiagGroupID id) const {
|
||||
return state.isIgnoredDiagnosticGroup(id);
|
||||
}
|
||||
|
||||
bool isIgnoredDiagnosticGroupTree(DiagGroupID id) const {
|
||||
return state.isIgnoredDiagnosticGroupTree(id);
|
||||
}
|
||||
|
||||
bool isIgnoredDiagnostic(DiagID id) const {
|
||||
return state.isIgnoredDiagnostic(id);
|
||||
void ignoreDiagnostic(DiagID id) {
|
||||
state.compilerInternalIgnoreDiagnostic(id);
|
||||
}
|
||||
|
||||
void resetHadAnyError() {
|
||||
|
||||
@@ -35,63 +35,66 @@
|
||||
#define DEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
#include "swift/AST/DefineDiagnosticGroupsMacros.h"
|
||||
|
||||
// GROUP(Name, DocsFile)
|
||||
// GROUP_LINK(Parent, Child)
|
||||
// GROUP(Name,Option,DocsFile)
|
||||
// GROUP_LINK(Parent,Child)
|
||||
|
||||
GROUP(no_group, "")
|
||||
GROUP(no_group,none,"")
|
||||
|
||||
GROUP(ActorIsolatedCall, "actor-isolated-call")
|
||||
GROUP(AlwaysAvailableDomain, "always-available-domain")
|
||||
GROUP(AvailabilityUnrecognizedName, "availability-unrecognized-name")
|
||||
GROUP(ClangDeclarationImport, "clang-declaration-import")
|
||||
GROUP(CompilationCaching, "compilation-caching")
|
||||
GROUP(ConformanceIsolation, "conformance-isolation")
|
||||
GROUP(ForeignReferenceType, "foreign-reference-type")
|
||||
GROUP(DeprecatedDeclaration, "deprecated-declaration")
|
||||
GROUP(DynamicCallable, "dynamic-callable-requirements")
|
||||
GROUP(DynamicExclusivity, "dynamic-exclusivity")
|
||||
GROUP(EmbeddedRestrictions, "embedded-restrictions")
|
||||
GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
|
||||
GROUP(ExclusivityViolation, "exclusivity-violation")
|
||||
GROUP(ExistentialAny, "existential-any")
|
||||
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
|
||||
GROUP(ExistentialType, "existential-type")
|
||||
GROUP(ImplementationOnlyDeprecated, "implementation-only-deprecated")
|
||||
GROUP(IsolatedConformances, "isolated-conformances")
|
||||
GROUP(MemberImportVisibility, "member-import-visibility")
|
||||
GROUP(MissingModuleOnKnownPaths, "missing-module-on-known-paths")
|
||||
GROUP(ModuleNotTestable, "module-not-testable")
|
||||
GROUP(ModuleVersionMissing, "module-version-missing")
|
||||
GROUP(MultipleInheritance, "multiple-inheritance")
|
||||
GROUP(MutableGlobalVariable, "mutable-global-variable")
|
||||
GROUP(NominalTypes, "nominal-types")
|
||||
GROUP(NonisolatedNonsendingByDefault, "nonisolated-nonsending-by-default")
|
||||
GROUP(OpaqueTypeInference, "opaque-type-inference")
|
||||
GROUP(PerformanceHints, "performance-hints")
|
||||
GROUP(PreconcurrencyImport, "preconcurrency-import")
|
||||
GROUP(PropertyWrappers, "property-wrapper-requirements")
|
||||
GROUP(ProtocolTypeNonConformance, "protocol-type-non-conformance")
|
||||
GROUP(RegionIsolation, "region-isolation")
|
||||
GROUP(ResultBuilderMethods, "result-builder-methods")
|
||||
GROUP(ReturnTypeImplicitCopy, "return-type-implicit-copy")
|
||||
GROUP(SemanticCopies, "semantic-copies")
|
||||
GROUP(SendableClosureCaptures, "sendable-closure-captures")
|
||||
GROUP(SendableMetatypes, "sendable-metatypes")
|
||||
GROUP(SendingClosureRisksDataRace, "sending-closure-risks-data-race")
|
||||
GROUP(SendingRisksDataRace, "sending-risks-data-race")
|
||||
GROUP(StrictLanguageFeatures, "strict-language-features")
|
||||
GROUP(StrictMemorySafety, "strict-memory-safety")
|
||||
GROUP(StringInterpolationConformance, "string-interpolation-conformance")
|
||||
GROUP(TemporaryPointers, "temporary-pointers")
|
||||
GROUP(TrailingClosureMatching, "trailing-closure-matching")
|
||||
GROUP(UnknownWarningGroup, "unknown-warning-group")
|
||||
GROUP(WeakMutability, "weak-mutability")
|
||||
GROUP(ActorIsolatedCall,none,"actor-isolated-call")
|
||||
GROUP(AlwaysAvailableDomain,none,"always-available-domain")
|
||||
GROUP(AvailabilityUnrecognizedName,none,"availability-unrecognized-name")
|
||||
GROUP(ClangDeclarationImport,none,"clang-declaration-import")
|
||||
GROUP(CompilationCaching,none,"compilation-caching")
|
||||
GROUP(ConformanceIsolation,none,"conformance-isolation")
|
||||
GROUP(ForeignReferenceType,none,"foreign-reference-type")
|
||||
GROUP(DeprecatedDeclaration,none,"deprecated-declaration")
|
||||
GROUP(DynamicExclusivity,DefaultIgnoreWarnings,"dynamic-exclusivity")
|
||||
GROUP(DynamicCallable,none,"dynamic-callable-requirements")
|
||||
GROUP(EmbeddedRestrictions,DefaultIgnoreWarnings,"embedded-restrictions")
|
||||
GROUP(ErrorInFutureSwiftVersion,none,"error-in-future-swift-version")
|
||||
GROUP(ExclusivityViolation,none,"exclusivity-violation")
|
||||
GROUP(ExistentialAny,none,"existential-any")
|
||||
GROUP(ExistentialMemberAccess,none,"existential-member-access-limitations")
|
||||
GROUP(ExistentialType,none,"existential-type")
|
||||
GROUP(ImplementationOnlyDeprecated,none,"implementation-only-deprecated")
|
||||
GROUP(IsolatedConformances,none,"isolated-conformances")
|
||||
GROUP(MemberImportVisibility,none,"member-import-visibility")
|
||||
GROUP(MissingModuleOnKnownPaths,none,"missing-module-on-known-paths")
|
||||
GROUP(ModuleNotTestable,none,"module-not-testable")
|
||||
GROUP(ModuleVersionMissing,none,"module-version-missing")
|
||||
GROUP(MultipleInheritance,none,"multiple-inheritance")
|
||||
GROUP(MutableGlobalVariable,none,"mutable-global-variable")
|
||||
GROUP(NominalTypes,none,"nominal-types")
|
||||
GROUP(NonisolatedNonsendingByDefault,none,"nonisolated-nonsending-by-default")
|
||||
GROUP(OpaqueTypeInference,none,"opaque-type-inference")
|
||||
GROUP(PerformanceHints,DefaultIgnoreWarnings,"performance-hints")
|
||||
GROUP(PreconcurrencyImport,DefaultIgnoreWarnings,"preconcurrency-import")
|
||||
GROUP(PropertyWrappers,none,"property-wrapper-requirements")
|
||||
GROUP(ProtocolTypeNonConformance,none,"protocol-type-non-conformance")
|
||||
GROUP(RegionIsolation,none,"region-isolation")
|
||||
GROUP(ResultBuilderMethods,none,"result-builder-methods")
|
||||
GROUP(ReturnTypeImplicitCopy,none,"return-type-implicit-copy")
|
||||
GROUP(SendableClosureCaptures,none,"sendable-closure-captures")
|
||||
GROUP(SendableMetatypes,none,"sendable-metatypes")
|
||||
GROUP(SemanticCopies,DefaultIgnoreWarnings,"semantic-copies")
|
||||
GROUP(SendingClosureRisksDataRace,none,"sending-closure-risks-data-race")
|
||||
GROUP(SendingRisksDataRace,none,"sending-risks-data-race")
|
||||
GROUP(StrictLanguageFeatures,none,"strict-language-features")
|
||||
GROUP(UnrecognizedStrictLanguageFeatures,DefaultIgnoreWarnings,"strict-language-features")
|
||||
GROUP(StrictMemorySafety,none,"strict-memory-safety")
|
||||
GROUP(StringInterpolationConformance,none,"string-interpolation-conformance")
|
||||
GROUP(TemporaryPointers,none,"temporary-pointers")
|
||||
GROUP(TrailingClosureMatching,none,"trailing-closure-matching")
|
||||
GROUP(UnknownWarningGroup,none,"unknown-warning-group")
|
||||
GROUP(WeakMutability,none,"weak-mutability")
|
||||
|
||||
GROUP_LINK(PerformanceHints, ExistentialType)
|
||||
GROUP_LINK(PerformanceHints, ReturnTypeImplicitCopy)
|
||||
GROUP_LINK(PerformanceHints,ExistentialType)
|
||||
GROUP_LINK(PerformanceHints,ReturnTypeImplicitCopy)
|
||||
|
||||
GROUP_LINK(RegionIsolation, SendingClosureRisksDataRace)
|
||||
GROUP_LINK(RegionIsolation, SendingRisksDataRace)
|
||||
GROUP_LINK(RegionIsolation,SendingClosureRisksDataRace)
|
||||
GROUP_LINK(RegionIsolation,SendingRisksDataRace)
|
||||
|
||||
GROUP_LINK(StrictLanguageFeatures, UnrecognizedStrictLanguageFeatures)
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
#include "swift/AST/DefineDiagnosticGroupsMacros.h"
|
||||
|
||||
@@ -24,16 +24,25 @@
|
||||
#include <unordered_map>
|
||||
|
||||
namespace swift {
|
||||
enum class DiagnosticGroupOptions {
|
||||
/// No options.
|
||||
none,
|
||||
|
||||
/// The diagnostic warnings belonging to this group should be ignored by default,
|
||||
/// but will be re-enabled by various warning options (-Wwarning, -Werror).
|
||||
DefaultIgnoreWarnings,
|
||||
};
|
||||
|
||||
enum class DiagID : uint32_t;
|
||||
|
||||
enum class DiagGroupID : uint16_t {
|
||||
#define GROUP(Name, Version) Name,
|
||||
enum class DiagGroupID : uint32_t {
|
||||
#define GROUP(Name, Option, DocsFile) Name,
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
|
||||
constexpr const auto DiagGroupsCount = [] {
|
||||
size_t count = 0;
|
||||
#define GROUP(Name, Version) ++count;
|
||||
#define GROUP(Name, Option, DocsFile) ++count;
|
||||
#include "DiagnosticGroups.def"
|
||||
return count;
|
||||
}();
|
||||
@@ -45,9 +54,30 @@ struct DiagGroupInfo {
|
||||
llvm::ArrayRef<DiagGroupID> supergroups;
|
||||
llvm::ArrayRef<DiagGroupID> subgroups;
|
||||
llvm::ArrayRef<DiagID> diagnostics;
|
||||
bool defaultIgnoreWarnings : 1;
|
||||
|
||||
constexpr DiagGroupInfo(DiagGroupID groupID, std::string_view name,
|
||||
std::string_view documentationFile,
|
||||
llvm::ArrayRef<DiagGroupID> supergroups,
|
||||
llvm::ArrayRef<DiagGroupID> subgroups,
|
||||
llvm::ArrayRef<DiagID> diagnostics,
|
||||
bool defaultIgnoreWarnings)
|
||||
: id(groupID), name(name), documentationFile(documentationFile),
|
||||
supergroups(supergroups), subgroups(subgroups), diagnostics(diagnostics),
|
||||
defaultIgnoreWarnings(defaultIgnoreWarnings) {}
|
||||
|
||||
constexpr DiagGroupInfo(DiagGroupID groupID, std::string_view name,
|
||||
std::string_view documentationFile,
|
||||
DiagnosticGroupOptions opts,
|
||||
llvm::ArrayRef<DiagGroupID> supergroups,
|
||||
llvm::ArrayRef<DiagGroupID> subgroups,
|
||||
llvm::ArrayRef<DiagID> diagnostics)
|
||||
: DiagGroupInfo(groupID, name, documentationFile, supergroups,
|
||||
subgroups, diagnostics,
|
||||
opts == DiagnosticGroupOptions::DefaultIgnoreWarnings) {}
|
||||
|
||||
void traverseDepthFirst(
|
||||
llvm::function_ref<void(const DiagGroupInfo &)> func) const;
|
||||
llvm::function_ref<void(const DiagGroupInfo &)> func) const;
|
||||
};
|
||||
|
||||
extern const std::array<DiagGroupInfo, DiagGroupsCount> diagnosticGroupsInfo;
|
||||
|
||||
@@ -40,12 +40,12 @@ WARNING(warning_upcoming_feature_on_by_default, none,
|
||||
"upcoming feature '%0' is already enabled as of Swift version %1",
|
||||
(StringRef, unsigned))
|
||||
|
||||
GROUPED_WARNING(unrecognized_feature, StrictLanguageFeatures, DefaultIgnore,
|
||||
GROUPED_WARNING(unrecognized_feature, UnrecognizedStrictLanguageFeatures, none,
|
||||
"'%0' is not a recognized "
|
||||
"%select{experimental|upcoming}1 feature",
|
||||
(StringRef, bool))
|
||||
|
||||
GROUPED_WARNING(feature_not_experimental, StrictLanguageFeatures, DefaultIgnore,
|
||||
GROUPED_WARNING(feature_not_experimental, UnrecognizedStrictLanguageFeatures, none,
|
||||
"'%0' is not an experimental feature, "
|
||||
"use -%select{disable|enable}1-upcoming-feature instead",
|
||||
(StringRef, bool))
|
||||
|
||||
@@ -435,18 +435,18 @@ NOTE(performance_called_from,none,
|
||||
"called from here", ())
|
||||
|
||||
// ManualOwnership diagnostics
|
||||
GROUPED_WARNING(manualownership_copy,SemanticCopies,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_copy,SemanticCopies,none,
|
||||
"implicit 'copy' happens here; please report this vague diagnostic as a bug", ())
|
||||
GROUPED_WARNING(manualownership_copy_happened,SemanticCopies,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_copy_happened,SemanticCopies,none,
|
||||
"accessing %0 may produce a copy; write 'copy' to acknowledge or 'consume' to elide", (Identifier))
|
||||
GROUPED_WARNING(manualownership_copy_demanded,SemanticCopies,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_copy_demanded,SemanticCopies,none,
|
||||
"independent copy of %0 is required here; write 'copy' to acknowledge or 'consume' to elide", (Identifier))
|
||||
GROUPED_WARNING(manualownership_copy_captured,SemanticCopies,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_copy_captured,SemanticCopies,none,
|
||||
"closure capture of '%0' requires independent copy of it; write [%0 = copy %0] in the closure's capture list to acknowledge", (StringRef))
|
||||
|
||||
GROUPED_WARNING(manualownership_exclusivity,DynamicExclusivity,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_exclusivity,DynamicExclusivity,none,
|
||||
"exclusive access here will be checked at runtime; please report this vague diagnostic as a bug", ())
|
||||
GROUPED_WARNING(manualownership_exclusivity_named,DynamicExclusivity,DefaultIgnore,
|
||||
GROUPED_WARNING(manualownership_exclusivity_named,DynamicExclusivity,none,
|
||||
"accessing %0 here may incur runtime exclusivity check%1", (Identifier, StringRef))
|
||||
|
||||
// 'transparent' diagnostics
|
||||
|
||||
@@ -2859,7 +2859,7 @@ WARNING(add_predates_concurrency_import,none,
|
||||
"'Sendable'-related %select{warnings|errors}0 from module %1"
|
||||
"%select{| as warnings}0", (bool, Identifier))
|
||||
GROUPED_WARNING(remove_predates_concurrency_import,PreconcurrencyImport,
|
||||
DefaultIgnore,
|
||||
none,
|
||||
"'@preconcurrency' on module %0 has no effect", (Identifier))
|
||||
WARNING(remove_public_import,none,
|
||||
"public import of %0 was not used in public declarations or inlinable code",
|
||||
@@ -8662,18 +8662,18 @@ GROUPED_ERROR(weak_unowned_in_embedded_swift, EmbeddedRestrictions, none,
|
||||
(ReferenceOwnership))
|
||||
|
||||
GROUPED_WARNING(untyped_throws_in_embedded_swift, EmbeddedRestrictions,
|
||||
DefaultIgnore,
|
||||
none,
|
||||
"untyped throws is not available in Embedded Swift; add a thrown error type with '(type)'", ())
|
||||
GROUPED_WARNING(generic_nonfinal_in_embedded_swift, EmbeddedRestrictions,
|
||||
DefaultIgnore,
|
||||
none,
|
||||
"generic %kind0 in a class %select{must be 'final'|cannot be 'required'}1 in Embedded Swift",
|
||||
(const Decl *, bool))
|
||||
GROUPED_WARNING(use_generic_member_of_existential_in_embedded_swift,
|
||||
EmbeddedRestrictions, DefaultIgnore,
|
||||
EmbeddedRestrictions, none,
|
||||
"cannot use generic %kind0 on a value of type %1 in Embedded Swift",
|
||||
(const Decl *, Type))
|
||||
GROUPED_WARNING(dynamic_cast_involving_protocol_in_embedded_swift,
|
||||
EmbeddedRestrictions, DefaultIgnore,
|
||||
EmbeddedRestrictions, none,
|
||||
"cannot perform a dynamic cast to a type involving %kind0 in Embedded Swift",
|
||||
(const Decl *))
|
||||
|
||||
@@ -8992,33 +8992,33 @@ ERROR(conformance_repression_only_on_struct_class_enum,none,
|
||||
// MARK: Swift Performance hints
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
GROUPED_WARNING(perf_hint_function_returns_array,ReturnTypeImplicitCopy,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_function_returns_array,ReturnTypeImplicitCopy,none,
|
||||
"Performance: %0 returns a%select{ dictionary|n array}1, leading to implicit copies. "
|
||||
"Consider using an 'inout' parameter instead.", (const FuncDecl *, bool))
|
||||
GROUPED_WARNING(perf_hint_closure_returns_array,ReturnTypeImplicitCopy,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_closure_returns_array,ReturnTypeImplicitCopy,none,
|
||||
"Performance: closure returns a%select{ dictionary|n array}0, leading to implicit copies. "
|
||||
"Consider using an 'inout' parameter instead.", (bool))
|
||||
|
||||
GROUPED_WARNING(perf_hint_param_expects_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_param_expects_existential,ExistentialType,none,
|
||||
"Performance: %0 expects an existential, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.",
|
||||
(const ParamDecl*))
|
||||
GROUPED_WARNING(perf_hint_func_returns_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_func_returns_existential,ExistentialType,none,
|
||||
"Performance: %0 returns an existential, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.",
|
||||
(const FuncDecl*))
|
||||
GROUPED_WARNING(perf_hint_closure_returns_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_closure_returns_existential,ExistentialType,none,
|
||||
"Performance: closure returns an existential, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.", ())
|
||||
GROUPED_WARNING(perf_hint_var_uses_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_var_uses_existential,ExistentialType,none,
|
||||
"Performance: %0 uses an existential, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.",
|
||||
(const VarDecl *))
|
||||
GROUPED_WARNING(perf_hint_any_pattern_uses_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_any_pattern_uses_existential,ExistentialType,none,
|
||||
"Performance: declaration uses an existential, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.",
|
||||
())
|
||||
GROUPED_WARNING(perf_hint_typealias_uses_existential,ExistentialType,DefaultIgnore,
|
||||
GROUPED_WARNING(perf_hint_typealias_uses_existential,ExistentialType,none,
|
||||
"Performance: %0 aliases an existential type, leading to heap allocation, reference counting, "
|
||||
"and dynamic dispatch. Consider using generic constraints or concrete types instead.",
|
||||
(const TypeAliasDecl *))
|
||||
|
||||
@@ -77,11 +77,6 @@ enum class DiagnosticOptions {
|
||||
|
||||
/// A diagnostic warning about an unused element.
|
||||
NoUsage,
|
||||
|
||||
/// The diagnostic should be ignored by default, but will be re-enabled
|
||||
/// by various warning options (-Wwarning, -Werror). This only makes sense
|
||||
/// for warnings.
|
||||
DefaultIgnore,
|
||||
};
|
||||
struct StoredDiagnosticInfo {
|
||||
DiagnosticKind kind : 2;
|
||||
@@ -90,17 +85,16 @@ struct StoredDiagnosticInfo {
|
||||
bool isAPIDigesterBreakage : 1;
|
||||
bool isDeprecation : 1;
|
||||
bool isNoUsage : 1;
|
||||
bool defaultIgnore : 1;
|
||||
DiagGroupID groupID;
|
||||
|
||||
constexpr StoredDiagnosticInfo(DiagnosticKind k, bool firstBadToken,
|
||||
bool fatal, bool isAPIDigesterBreakage,
|
||||
bool deprecation, bool noUsage,
|
||||
bool defaultIgnore, DiagGroupID groupID)
|
||||
DiagGroupID groupID)
|
||||
: kind(k), pointsToFirstBadToken(firstBadToken), isFatal(fatal),
|
||||
isAPIDigesterBreakage(isAPIDigesterBreakage),
|
||||
isDeprecation(deprecation), isNoUsage(noUsage),
|
||||
defaultIgnore(defaultIgnore), groupID(groupID) {}
|
||||
groupID(groupID) {}
|
||||
constexpr StoredDiagnosticInfo(DiagnosticKind k, DiagnosticOptions opts,
|
||||
DiagGroupID groupID)
|
||||
: StoredDiagnosticInfo(k,
|
||||
@@ -109,7 +103,6 @@ struct StoredDiagnosticInfo {
|
||||
opts == DiagnosticOptions::APIDigesterBreakage,
|
||||
opts == DiagnosticOptions::Deprecation,
|
||||
opts == DiagnosticOptions::NoUsage,
|
||||
opts == DiagnosticOptions::DefaultIgnore,
|
||||
groupID) {}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
@@ -154,14 +147,29 @@ static constexpr const char *const fixItStrings[] = {
|
||||
};
|
||||
|
||||
DiagnosticState::DiagnosticState() {
|
||||
// Initialize our ignored diagnostics to defaults
|
||||
ignoredDiagnostics.reserve(NumDiagIDs);
|
||||
for (const auto &info : storedDiagnosticInfos) {
|
||||
ignoredDiagnostics.push_back(info.defaultIgnore);
|
||||
}
|
||||
// Initialize ignored diagnostic groups to defaults
|
||||
ignoredDiagnosticGroups.resize(DiagGroupsCount);
|
||||
// Ensure that for each `DefaultIgnoreWarnings` group,
|
||||
// we propagate this behavior to its child groups.
|
||||
for (const auto &groupInfo : diagnosticGroupsInfo)
|
||||
if (groupInfo.defaultIgnoreWarnings)
|
||||
getDiagGroupInfoByID(groupInfo.id).traverseDepthFirst([&](auto group) {
|
||||
ignoredDiagnosticGroups[(unsigned)group.id] = true;
|
||||
});
|
||||
|
||||
// Initialize warningsAsErrors to default
|
||||
warningsAsErrors.resize(DiagGroupsCount);
|
||||
|
||||
// Initialize compilerIgnoredDiagnostics
|
||||
compilerIgnoredDiagnostics.resize(NumDiagIDs);
|
||||
}
|
||||
|
||||
bool DiagnosticState::isIgnoredDiagnosticGroupTree(DiagGroupID id) const {
|
||||
bool anyEnabled = false;
|
||||
getDiagGroupInfoByID(id).traverseDepthFirst([&](auto group) {
|
||||
anyEnabled |= !isIgnoredDiagnosticGroup(group.id);
|
||||
});
|
||||
return !anyEnabled;
|
||||
}
|
||||
|
||||
Diagnostic::Diagnostic(DiagID ID)
|
||||
@@ -597,10 +605,8 @@ void DiagnosticEngine::setWarningsAsErrorsRules(
|
||||
if (auto groupID = getDiagGroupIDByName(name);
|
||||
groupID && *groupID != DiagGroupID::no_group) {
|
||||
getDiagGroupInfoByID(*groupID).traverseDepthFirst([&](auto group) {
|
||||
state.setWarningsAsErrorsForDiagGroupID(*groupID, isEnabled);
|
||||
for (DiagID diagID : group.diagnostics) {
|
||||
state.setIgnoredDiagnostic(diagID, false);
|
||||
}
|
||||
state.setWarningsAsErrorsForDiagGroupID(group.id, isEnabled);
|
||||
state.setIgnoredDiagnosticGroup(group.id, false);
|
||||
});
|
||||
} else {
|
||||
unknownGroups.push_back(std::string(name));
|
||||
@@ -1343,14 +1349,16 @@ DiagnosticState::determineBehavior(const Diagnostic &diag) const {
|
||||
if (!showDiagnosticsAfterFatalError && lvl != DiagnosticBehavior::Note)
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
|
||||
// 3) If the user ignored this specific diagnostic, follow that
|
||||
if (ignoredDiagnostics[(unsigned)diag.getID()])
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
// Handle compiler-internal ignored diagnostics
|
||||
if (compilerIgnoredDiagnostics[(unsigned)diag.getID()])
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
|
||||
// 4) If the user substituted a different behavior for this behavior, apply
|
||||
// 3) If the user substituted a different behavior for this warning, apply
|
||||
// that change
|
||||
if (lvl == DiagnosticBehavior::Warning) {
|
||||
if (getWarningsAsErrorsForDiagGroupID(diag.getGroupID()))
|
||||
if (isIgnoredDiagnosticGroup(diag.getGroupID()))
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
else if (getWarningsAsErrorsForDiagGroupID(diag.getGroupID()))
|
||||
lvl = DiagnosticBehavior::Error;
|
||||
if (suppressWarnings)
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
|
||||
@@ -68,7 +68,7 @@ constexpr const auto diagnosticGroupConnections = [] {
|
||||
constexpr auto diagnosticsCount = std::get<2>(sizes);
|
||||
|
||||
// Declare all edges
|
||||
#define GROUP(Name, DocsFile) \
|
||||
#define GROUP(Name, Option, DocsFile) \
|
||||
std::array<DiagGroupID, supergroupsCount[(size_t)DiagGroupID::Name]> \
|
||||
Name##_supergroups{}; \
|
||||
std::array<DiagGroupID, subgroupsCount[(size_t)DiagGroupID::Name]> \
|
||||
@@ -92,7 +92,7 @@ constexpr const auto diagnosticGroupConnections = [] {
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
|
||||
// Produce the resulting structure with all the edges
|
||||
#define GROUP(Name, DocsFile) \
|
||||
#define GROUP(Name, Option, DocsFile) \
|
||||
GroupConnections(Name##_supergroups, Name##_subgroups, Name##_diagnostics),
|
||||
return std::tuple{
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
@@ -100,7 +100,7 @@ constexpr const auto diagnosticGroupConnections = [] {
|
||||
}();
|
||||
|
||||
std::unordered_map<std::string_view, DiagGroupID> nameToIDMap{
|
||||
#define GROUP(Name, DocsFile) {#Name, DiagGroupID::Name},
|
||||
#define GROUP(Name, Option, DocsFile) {#Name, DiagGroupID::Name},
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
|
||||
@@ -119,11 +119,12 @@ void traverseDepthFirst(DiagGroupID id,
|
||||
} // end anonymous namespace
|
||||
|
||||
constexpr const std::array<DiagGroupInfo, DiagGroupsCount> diagnosticGroupsInfo{
|
||||
#define GROUP(Name, DocsFile) \
|
||||
#define GROUP(Name, Option, DocsFile) \
|
||||
DiagGroupInfo{ \
|
||||
DiagGroupID::Name, \
|
||||
#Name, \
|
||||
DocsFile, \
|
||||
DiagnosticGroupOptions::Option, \
|
||||
llvm::ArrayRef<DiagGroupID>( \
|
||||
std::get<(size_t)DiagGroupID::Name>(diagnosticGroupConnections) \
|
||||
.supergroups), \
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "swift/AST/ASTWalker.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/AST/DiagnosticGroups.h"
|
||||
#include "swift/AST/DiagnosticsSema.h"
|
||||
#include "swift/AST/Evaluator.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
@@ -30,22 +31,7 @@
|
||||
using namespace swift;
|
||||
|
||||
bool swift::performanceHintDiagnosticsEnabled(ASTContext &ctx) {
|
||||
return !ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_closure_returns_array.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_function_returns_array.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_param_expects_existential.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_func_returns_existential.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_closure_returns_existential.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_var_uses_existential.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_any_pattern_uses_existential.ID) ||
|
||||
!ctx.Diags.isIgnoredDiagnostic(
|
||||
diag::perf_hint_typealias_uses_existential.ID);
|
||||
return !ctx.Diags.isIgnoredDiagnosticGroupTree(DiagGroupID::PerformanceHints);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "TypeCheckEmbedded.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/DiagnosticGroups.h"
|
||||
#include "swift/AST/DiagnosticsSema.h"
|
||||
#include "swift/AST/Effects.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
@@ -46,11 +47,11 @@ swift::shouldDiagnoseEmbeddedLimitations(const DeclContext *dc, SourceLoc loc,
|
||||
return defaultEmbeddedLimitationForError(dc, loc);
|
||||
}
|
||||
|
||||
// Check one of the Embedded restriction diagnostics that is ignored by
|
||||
// default. If it's still ignored, we won't diagnose anything.
|
||||
// limitations.
|
||||
// Check if the Embedded restriction diagnostics, which are ignored by
|
||||
// default, have been enabled. If it's still ignored, we won't diagnose
|
||||
// anything. limitations.
|
||||
auto &diags = dc->getASTContext().Diags;
|
||||
if (diags.isIgnoredDiagnostic(diag::untyped_throws_in_embedded_swift.ID))
|
||||
if (diags.isIgnoredDiagnosticGroup(DiagGroupID::EmbeddedRestrictions))
|
||||
return std::nullopt;
|
||||
|
||||
#if SWIFT_BUILD_SWIFT_SYNTAX
|
||||
|
||||
26
test/diagnostics/default-ignore-groups.swift
Normal file
26
test/diagnostics/default-ignore-groups.swift
Normal file
@@ -0,0 +1,26 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// Ignore `ReturnTypeImplicitCopy` warnings by-default, because its parent group (`PerformanceHints`) is marked `DefaultIgnoreWarnings`
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -verify
|
||||
|
||||
// Ensure enabled with `-Wwarning`
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -Wwarning ReturnTypeImplicitCopy -verify -verify-additional-prefix warnonly-
|
||||
|
||||
// Ensure enabled with `-Wwarning` on the parent group
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -Wwarning PerformanceHints -verify -verify-additional-prefix warnonly-
|
||||
|
||||
// Ensure enabled with `-Werror`
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -Werror ReturnTypeImplicitCopy -verify -verify-additional-prefix erronly-
|
||||
|
||||
// Ensure enabled with `-Werror` on the parent group
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -Werror PerformanceHints -verify -verify-additional-prefix erronly-
|
||||
|
||||
// Ensure enabling sibling group does not enable this group
|
||||
// RUN: %target-swift-frontend -typecheck %s -diagnostic-style llvm -verify -Werror ExistentialType
|
||||
|
||||
|
||||
func foo() -> [Int] {
|
||||
// expected-erronly-error@-1 {{Performance: 'foo()' returns an array, leading to implicit copies. Consider using an 'inout' parameter instead}}
|
||||
// expected-warnonly-warning@-2 {{Performance: 'foo()' returns an array, leading to implicit copies. Consider using an 'inout' parameter instead}}
|
||||
return [1,2,3,4,5,6]
|
||||
}
|
||||
Reference in New Issue
Block a user