mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Diagnostics] Add -[no-]warning-as-error flags for precise control over warning behavior
This commit adds new compiler options -no-warning-as-error/-warning-as-error which allows users to specify behavior for exact warnings and warning groups.
This commit is contained in:
@@ -379,7 +379,7 @@ struct BridgedPatternBindingEntry {
|
||||
// NOTE: This must be the same underlying value as C++ 'swift::DiagID' defined
|
||||
// in 'DiagnosticList.cpp'.
|
||||
enum ENUM_EXTENSIBILITY_ATTR(open) BridgedDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) BridgedDiagID_##ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) BridgedDiagID_##ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
|
||||
67
include/swift/AST/DefineDiagnosticGroupsMacros.h
Normal file
67
include/swift/AST/DefineDiagnosticGroupsMacros.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//===--- DefineDiagnosticGroupsMacros.def -----------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines macros defining diagnostic groups.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Define macros
|
||||
#if defined(DEFINE_DIAGNOSTIC_GROUPS_MACROS) && \
|
||||
!defined(UNDEFINE_DIAGNOSTIC_GROUPS_MACROS)
|
||||
|
||||
#undef DEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
|
||||
#if !(defined(GROUP) || defined(GROUP_LINK))
|
||||
#error No reqired macros defined. Define at least one of the following macros: GROUP(Name, DocsFile), GROUP_LINK(Parent, Child)
|
||||
#endif
|
||||
|
||||
// GROUP macro:
|
||||
// Declares a diagnostic group.
|
||||
// Parameters:
|
||||
// Name - group name as it appears in DiagGroupID enum and DiagGroupInfo.name
|
||||
// DocsFile - file with a human readable description for the group located in
|
||||
// userdocs/diagnostic_groups
|
||||
#ifndef GROUP
|
||||
#define GROUP(Name, DocsFile)
|
||||
#endif
|
||||
|
||||
// GROUP_LINK macro:
|
||||
// Establishes an edge in the diagnostic group graph between
|
||||
// a supergroup(Parent) and its subgroup(Child).
|
||||
// Parameters:
|
||||
// Parent - parent group name
|
||||
// Child - child group name
|
||||
#ifndef GROUP_LINK
|
||||
#define GROUP_LINK(Parent, Child)
|
||||
#endif
|
||||
|
||||
// Undefine macros
|
||||
#elif defined(UNDEFINE_DIAGNOSTIC_GROUPS_MACROS) && \
|
||||
!defined(DEFINE_DIAGNOSTIC_GROUPS_MACROS)
|
||||
|
||||
#undef UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
|
||||
#ifdef GROUP
|
||||
#undef GROUP
|
||||
#else
|
||||
#error Trying to undefine the diagnostic groups macros, but GROUP macro wasn't defined
|
||||
#endif
|
||||
|
||||
#ifdef GROUP_LINK
|
||||
#undef GROUP_LINK
|
||||
#else
|
||||
#error Trying to undefine the diagnostic groups macros, but GROUP_LINK macro wasn't defined
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error Invalid DefineDiagnosticGroupsMacros.h inclusion
|
||||
#endif
|
||||
@@ -17,29 +17,39 @@
|
||||
// Define macros
|
||||
#ifdef DEFINE_DIAGNOSTIC_MACROS
|
||||
|
||||
#if !(defined(DIAG) || (defined(ERROR) && defined(WARNING) && defined(NOTE) && \
|
||||
defined(REMARK)))
|
||||
#error Must define either DIAG or the set {ERROR,WARNING,NOTE,REMARK}
|
||||
#if !(defined(DIAG) || (defined(GROUPED_ERROR) && defined(GROUPED_WARNING) && \
|
||||
defined(NOTE) && defined(REMARK)))
|
||||
#error Must define either DIAG or the set {GROUPED_ERROR,GROUPED_WARNING,NOTE,REMARK}
|
||||
#endif
|
||||
|
||||
#ifndef GROUPED_ERROR
|
||||
#define GROUPED_ERROR(ID, Group, Options, Text, Signature) \
|
||||
DIAG(ERROR, ID, Group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef ERROR
|
||||
#define ERROR(ID, Options, Text, Signature) \
|
||||
DIAG(ERROR, ID, Options, Text, Signature)
|
||||
GROUPED_ERROR(ID, no_group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef GROUPED_WARNING
|
||||
#define GROUPED_WARNING(ID, Group, Options, Text, Signature) \
|
||||
DIAG(WARNING, ID, Group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef WARNING
|
||||
#define WARNING(ID, Options, Text, Signature) \
|
||||
DIAG(WARNING, ID, Options, Text, Signature)
|
||||
GROUPED_WARNING(ID, no_group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef NOTE
|
||||
#define NOTE(ID, Options, Text, Signature) \
|
||||
DIAG(NOTE, ID, Options, Text, Signature)
|
||||
DIAG(NOTE, ID, no_group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef REMARK
|
||||
#define REMARK(ID, Options, Text, Signature) \
|
||||
DIAG(REMARK, ID, Options, Text, Signature)
|
||||
DIAG(REMARK, ID, no_group, Options, Text, Signature)
|
||||
#endif
|
||||
|
||||
#ifndef FIXIT
|
||||
@@ -61,7 +71,9 @@
|
||||
#undef REMARK
|
||||
#undef NOTE
|
||||
#undef WARNING
|
||||
#undef GROUPED_WARNING
|
||||
#undef ERROR
|
||||
#undef GROUPED_ERROR
|
||||
#undef FIXIT
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "swift/AST/TypeLoc.h"
|
||||
#include "swift/Basic/Statistic.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "swift/Basic/WarningAsErrorRule.h"
|
||||
#include "swift/Localization/LocalizationFormat.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
@@ -851,8 +852,8 @@ namespace swift {
|
||||
/// Don't emit any remarks
|
||||
bool suppressRemarks = false;
|
||||
|
||||
/// Emit all warnings as errors
|
||||
bool warningsAsErrors = false;
|
||||
/// Treat these warnings as errors. Indicies here corespond to DiagID enum
|
||||
llvm::BitVector warningsAsErrors;
|
||||
|
||||
/// Whether a fatal error has occurred
|
||||
bool fatalErrorOccurred = false;
|
||||
@@ -893,9 +894,22 @@ namespace swift {
|
||||
void setSuppressRemarks(bool val) { suppressRemarks = val; }
|
||||
bool getSuppressRemarks() const { return suppressRemarks; }
|
||||
|
||||
/// Whether to treat warnings as errors
|
||||
void setWarningsAsErrors(bool val) { warningsAsErrors = val; }
|
||||
bool getWarningsAsErrors() const { return warningsAsErrors; }
|
||||
/// Whether a warning should be upgraded to an error or not
|
||||
void setWarningAsErrorForDiagID(DiagID id, bool value) {
|
||||
warningsAsErrors[(unsigned)id] = value;
|
||||
}
|
||||
bool getWarningAsErrorForDiagID(DiagID id) {
|
||||
return warningsAsErrors[(unsigned)id];
|
||||
}
|
||||
|
||||
/// Whether all warnings should be upgraded to errors or not
|
||||
void setAllWarningsAsErrors(bool value) {
|
||||
if (value) {
|
||||
warningsAsErrors.set();
|
||||
} else {
|
||||
warningsAsErrors.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void resetHadAnyError() {
|
||||
anyErrorOccurred = false;
|
||||
@@ -1105,11 +1119,13 @@ namespace swift {
|
||||
return state.getSuppressRemarks();
|
||||
}
|
||||
|
||||
/// Whether to treat warnings as errors
|
||||
void setWarningsAsErrors(bool val) { state.setWarningsAsErrors(val); }
|
||||
bool getWarningsAsErrors() const {
|
||||
return state.getWarningsAsErrors();
|
||||
}
|
||||
/// Apply rules specifing what warnings should or shouldn't be treated as
|
||||
/// errors. For group rules the string is either a group name defined by
|
||||
/// DiagnosticGroups.def
|
||||
/// Rules are applied in order they appear in the vector.
|
||||
/// In case the vector contains rules affecting the same diagnostic ID
|
||||
/// the last rule wins.
|
||||
void setWarningsAsErrorsRules(const std::vector<WarningAsErrorRule> &rules);
|
||||
|
||||
/// Whether to print diagnostic names after their messages
|
||||
void setPrintDiagnosticNames(bool val) {
|
||||
|
||||
33
include/swift/AST/DiagnosticGroups.def
Normal file
33
include/swift/AST/DiagnosticGroups.def
Normal file
@@ -0,0 +1,33 @@
|
||||
//===--- DiagnosticGroups.def - Diagnostic Groups ---------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines diagnostic groups and links between them.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
#include "swift/AST/DefineDiagnosticGroupsMacros.h"
|
||||
|
||||
// GROUP(Name, DocsFile)
|
||||
// GROUP_LINK(Parent, Child)
|
||||
|
||||
GROUP(no_group, "")
|
||||
|
||||
GROUP(deprecated, "deprecated.md")
|
||||
GROUP_LINK(deprecated, availability_deprecated)
|
||||
|
||||
GROUP(availability_deprecated, "availability_deprecated.md")
|
||||
|
||||
GROUP(unknown_warning_group, "unknown_warning_group.md")
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
#include "swift/AST/DefineDiagnosticGroupsMacros.h"
|
||||
59
include/swift/AST/DiagnosticGroups.h
Normal file
59
include/swift/AST/DiagnosticGroups.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//===--- DiagnosticGroups.h - Diagnostic Groups -----------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the diagnostic groups enumaration, group graph
|
||||
// and auxilary functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DIAGNOSTICGROUPS_H
|
||||
#define SWIFT_DIAGNOSTICGROUPS_H
|
||||
|
||||
#include "swift/AST/DiagnosticList.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace swift {
|
||||
|
||||
enum class DiagGroupID : uint16_t {
|
||||
#define GROUP(Name, Version) Name,
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
|
||||
constexpr const auto DiagGroupsCount = [] {
|
||||
size_t count = 0;
|
||||
#define GROUP(Name, Version) count++;
|
||||
#include "DiagnosticGroups.def"
|
||||
return count;
|
||||
}();
|
||||
|
||||
struct DiagGroupInfo {
|
||||
DiagGroupID id;
|
||||
std::string_view name;
|
||||
std::string_view version;
|
||||
llvm::ArrayRef<DiagGroupID> supergroups;
|
||||
llvm::ArrayRef<DiagGroupID> subgroups;
|
||||
llvm::ArrayRef<DiagID> diagnostics;
|
||||
|
||||
void traverseDepthFirst(
|
||||
llvm::function_ref<void(const DiagGroupInfo &)> func) const;
|
||||
};
|
||||
|
||||
extern const std::array<DiagGroupInfo, DiagGroupsCount> diagnosticGroupsInfo;
|
||||
const DiagGroupInfo &getDiagGroupInfoByID(DiagGroupID id);
|
||||
std::optional<DiagGroupID> getDiagGroupIDByName(std::string_view name);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_DIAGNOSTICGROUPS_H */
|
||||
43
include/swift/AST/DiagnosticList.h
Normal file
43
include/swift/AST/DiagnosticList.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//===--- DiagnosticList.h - Diagnostic Definitions --------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines all of the diagnostics emitted by Swift.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DIAGNOSTICLIST_H
|
||||
#define SWIFT_DIAGNOSTICLIST_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Enumeration describing all of possible diagnostics.
|
||||
///
|
||||
/// Each of the diagnostics described in Diagnostics.def has an entry in
|
||||
/// this enumeration type that uniquely identifies it.
|
||||
enum class DiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
static_assert(static_cast<uint32_t>(swift::DiagID::invalid_diagnostic) == 0,
|
||||
"0 is not the invalid diagnostic ID");
|
||||
|
||||
enum class FixItID : uint32_t {
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature)
|
||||
#define FIXIT(ID, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_DIAGNOSTICLIST_H */
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsClangImporter.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace swift {
|
||||
using DeclAttribute = const DeclAttribute *;
|
||||
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID, Text, Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID, Text, Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsCommon.def"
|
||||
} // end namespace diag
|
||||
} // end namespace swift
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsDriver.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,8 @@ ERROR(error_missing_arg_value,none,
|
||||
(StringRef, unsigned))
|
||||
ERROR(error_unknown_arg,none,
|
||||
"unknown argument: '%0'", (StringRef))
|
||||
GROUPED_WARNING(unknown_warning_group, unknown_warning_group, none,
|
||||
"unknown warning group: '%0'", (StringRef))
|
||||
ERROR(error_invalid_arg_value,none,
|
||||
"invalid value '%1' in '%0'", (StringRef, StringRef))
|
||||
ERROR(error_invalid_arg_combination,none,
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsFrontend.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsIDE.def"
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsIRGen.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsModuleDiffer.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID,Text,Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID, Text, Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsParse.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsRefactoring.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsSIL.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6639,19 +6639,20 @@ NOTE(availability_obsoleted, none,
|
||||
"%0 was obsoleted in %1 %2",
|
||||
(const ValueDecl *, StringRef, llvm::VersionTuple))
|
||||
|
||||
WARNING(availability_deprecated, Deprecation,
|
||||
"%0 %select{is|%select{is|was}3}1 "
|
||||
"deprecated%select{| in %2%select{| %4}3}1%select{|: %5}5",
|
||||
(const ValueDecl *, bool, StringRef, bool, llvm::VersionTuple,
|
||||
StringRef))
|
||||
GROUPED_WARNING(availability_deprecated, availability_deprecated, Deprecation,
|
||||
"%0 %select{is|%select{is|was}3}1 "
|
||||
"deprecated%select{| in %2%select{| %4}3}1%select{|: %5}5",
|
||||
(const ValueDecl *, bool, StringRef, bool, llvm::VersionTuple,
|
||||
StringRef))
|
||||
|
||||
WARNING(availability_deprecated_rename, Deprecation,
|
||||
"%0 %select{is|%select{is|was}3}1 "
|
||||
"deprecated%select{| in %2%select{| %4}3}1: "
|
||||
"%select{renamed to|replaced by}5%" REPLACEMENT_DECL_KIND_SELECT "6 "
|
||||
"'%7'",
|
||||
(const ValueDecl *, bool, StringRef, bool, llvm::VersionTuple, bool,
|
||||
unsigned, StringRef))
|
||||
GROUPED_WARNING(
|
||||
availability_deprecated_rename, availability_deprecated, Deprecation,
|
||||
"%0 %select{is|%select{is|was}3}1 "
|
||||
"deprecated%select{| in %2%select{| %4}3}1: "
|
||||
"%select{renamed to|replaced by}5%" REPLACEMENT_DECL_KIND_SELECT "6 "
|
||||
"'%7'",
|
||||
(const ValueDecl *, bool, StringRef, bool, llvm::VersionTuple, bool,
|
||||
unsigned, StringRef))
|
||||
#undef REPLACEMENT_DECL_KIND_SELECT
|
||||
|
||||
NOTE(note_deprecated_rename, none,
|
||||
|
||||
@@ -33,10 +33,10 @@ namespace swift {
|
||||
};
|
||||
|
||||
// Declare common diagnostics objects with their appropriate types.
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID,Text,Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
extern detail::DiagWithArguments<void Signature>::type ID;
|
||||
#define FIXIT(ID, Text, Signature) \
|
||||
extern detail::StructuredFixItWithArguments<void Signature>::type ID;
|
||||
#include "DiagnosticsSema.def"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#ifndef SWIFT_BASIC_DIAGNOSTICOPTIONS_H
|
||||
#define SWIFT_BASIC_DIAGNOSTICOPTIONS_H
|
||||
|
||||
#include "swift/Basic/WarningAsErrorRule.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include <vector>
|
||||
|
||||
namespace swift {
|
||||
|
||||
@@ -58,8 +60,8 @@ public:
|
||||
/// Suppress all remarks
|
||||
bool SuppressRemarks = false;
|
||||
|
||||
/// Treat all warnings as errors
|
||||
bool WarningsAsErrors = false;
|
||||
/// Rules for escalating warnings to errors
|
||||
std::vector<WarningAsErrorRule> WarningsAsErrorsRules;
|
||||
|
||||
/// When printing diagnostics, include the diagnostic name (diag::whatever) at
|
||||
/// the end.
|
||||
|
||||
48
include/swift/Basic/WarningAsErrorRule.h
Normal file
48
include/swift/Basic/WarningAsErrorRule.h
Normal file
@@ -0,0 +1,48 @@
|
||||
//===--- WarningAsErrorRule.h -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_BASIC_WARNINGASERRORRULE_H
|
||||
#define SWIFT_BASIC_WARNINGASERRORRULE_H
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Describes a rule how to treat a warning or all warnings.
|
||||
class WarningAsErrorRule {
|
||||
public:
|
||||
enum class Action { Disable, Enable };
|
||||
struct TargetAll {};
|
||||
struct TargetGroup {
|
||||
std::string name;
|
||||
};
|
||||
using Target = std::variant<TargetAll, TargetGroup>;
|
||||
|
||||
/// Init as a rule targeting all diagnostic groups
|
||||
WarningAsErrorRule(Action action) : action(action), target(TargetAll()) {}
|
||||
/// Init as a rule targeting a specific diagnostic group
|
||||
WarningAsErrorRule(Action action, const std::string &group)
|
||||
: action(action), target(TargetGroup{group}) {}
|
||||
|
||||
Action getAction() const { return action; }
|
||||
|
||||
Target getTarget() const { return target; }
|
||||
|
||||
private:
|
||||
Action action;
|
||||
Target target;
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_BASIC_WARNINGASERRORRULE_H
|
||||
@@ -799,13 +799,29 @@ def suppress_warnings : Flag<["-"], "suppress-warnings">,
|
||||
Flags<[FrontendOption]>,
|
||||
HelpText<"Suppress all warnings">;
|
||||
|
||||
def warning_treating_Group : OptionGroup<"<options to control warning treating>">;
|
||||
|
||||
def warnings_as_errors : Flag<["-"], "warnings-as-errors">,
|
||||
Group<warning_treating_Group>,
|
||||
Flags<[FrontendOption]>,
|
||||
HelpText<"Treat warnings as errors">;
|
||||
|
||||
def warning_as_error : Separate<["-"], "warning-as-error">,
|
||||
Group<warning_treating_Group>,
|
||||
Flags<[FrontendOption, HelpHidden]>,
|
||||
MetaVarName<"<diagnostic_group>">,
|
||||
HelpText<"Treat this warning group as error">;
|
||||
|
||||
def no_warnings_as_errors : Flag<["-"], "no-warnings-as-errors">,
|
||||
Group<warning_treating_Group>,
|
||||
Flags<[FrontendOption]>,
|
||||
HelpText<"Don't treat warnings as errors">;
|
||||
|
||||
def no_warning_as_error : Separate<["-"], "no-warning-as-error">,
|
||||
Group<warning_treating_Group>,
|
||||
Flags<[FrontendOption, HelpHidden]>,
|
||||
MetaVarName<"<diagnostic_group>">,
|
||||
HelpText<"Don't treat this warning group as error">;
|
||||
|
||||
def suppress_remarks : Flag<["-"], "suppress-remarks">,
|
||||
Flags<[FrontendOption]>,
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace {
|
||||
// Reproduce the DiagIDs, as we want both the size and access to the raw ids
|
||||
// themselves.
|
||||
enum LocalDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
NumDiags
|
||||
};
|
||||
@@ -90,9 +90,9 @@ ModuleDifferDiagsConsumer::ModuleDifferDiagsConsumer(bool DiagnoseModuleDiff,
|
||||
llvm::raw_ostream &OS):
|
||||
PrintingDiagnosticConsumer(OS), OS(OS),
|
||||
DiagnoseModuleDiff(DiagnoseModuleDiff) {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) \
|
||||
auto ID = getCategoryName(LocalDiagID::ID); \
|
||||
assert(!ID.empty()); \
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
auto ID = getCategoryName(LocalDiagID::ID); \
|
||||
assert(!ID.empty()); \
|
||||
AllDiags[ID] = std::set<std::string>();
|
||||
#include "swift/AST/DiagnosticsModuleDiffer.def"
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ add_swift_host_library(swiftAST STATIC
|
||||
DiagnosticBridge.cpp
|
||||
DiagnosticConsumer.cpp
|
||||
DiagnosticEngine.cpp
|
||||
DiagnosticGroups.cpp
|
||||
DiagnosticList.cpp
|
||||
DistributedDecl.cpp
|
||||
DocComment.cpp
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/DiagnosticGroups.h"
|
||||
#include "swift/AST/DiagnosticSuppression.h"
|
||||
#include "swift/AST/DiagnosticsCommon.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
@@ -78,26 +79,29 @@ struct StoredDiagnosticInfo {
|
||||
bool isAPIDigesterBreakage : 1;
|
||||
bool isDeprecation : 1;
|
||||
bool isNoUsage : 1;
|
||||
DiagGroupID groupID;
|
||||
|
||||
constexpr StoredDiagnosticInfo(DiagnosticKind k, bool firstBadToken,
|
||||
bool fatal, bool isAPIDigesterBreakage,
|
||||
bool deprecation, bool noUsage)
|
||||
bool deprecation, bool noUsage,
|
||||
DiagGroupID groupID)
|
||||
: kind(k), pointsToFirstBadToken(firstBadToken), isFatal(fatal),
|
||||
isAPIDigesterBreakage(isAPIDigesterBreakage), isDeprecation(deprecation),
|
||||
isNoUsage(noUsage) {}
|
||||
constexpr StoredDiagnosticInfo(DiagnosticKind k, DiagnosticOptions opts)
|
||||
isAPIDigesterBreakage(isAPIDigesterBreakage),
|
||||
isDeprecation(deprecation), isNoUsage(noUsage), groupID(groupID) {}
|
||||
constexpr StoredDiagnosticInfo(DiagnosticKind k, DiagnosticOptions opts,
|
||||
DiagGroupID groupID)
|
||||
: StoredDiagnosticInfo(k,
|
||||
opts == DiagnosticOptions::PointsToFirstBadToken,
|
||||
opts == DiagnosticOptions::Fatal,
|
||||
opts == DiagnosticOptions::APIDigesterBreakage,
|
||||
opts == DiagnosticOptions::Deprecation,
|
||||
opts == DiagnosticOptions::NoUsage) {}
|
||||
opts == DiagnosticOptions::NoUsage, groupID) {}
|
||||
};
|
||||
|
||||
// Reproduce the DiagIDs, as we want both the size and access to the raw ids
|
||||
// themselves.
|
||||
enum LocalDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
NumDiags
|
||||
};
|
||||
@@ -105,14 +109,18 @@ enum LocalDiagID : uint32_t {
|
||||
|
||||
// TODO: categorization
|
||||
static const constexpr StoredDiagnosticInfo storedDiagnosticInfos[] = {
|
||||
#define ERROR(ID, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Error, DiagnosticOptions::Options),
|
||||
#define WARNING(ID, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Warning, DiagnosticOptions::Options),
|
||||
#define GROUPED_ERROR(ID, Group, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Error, DiagnosticOptions::Options, \
|
||||
DiagGroupID::Group),
|
||||
#define GROUPED_WARNING(ID, Group, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Warning, DiagnosticOptions::Options, \
|
||||
DiagGroupID::Group),
|
||||
#define NOTE(ID, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Note, DiagnosticOptions::Options),
|
||||
StoredDiagnosticInfo(DiagnosticKind::Note, DiagnosticOptions::Options, \
|
||||
DiagGroupID::no_group),
|
||||
#define REMARK(ID, Options, Text, Signature) \
|
||||
StoredDiagnosticInfo(DiagnosticKind::Remark, DiagnosticOptions::Options),
|
||||
StoredDiagnosticInfo(DiagnosticKind::Remark, DiagnosticOptions::Options, \
|
||||
DiagGroupID::no_group),
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
static_assert(sizeof(storedDiagnosticInfos) / sizeof(StoredDiagnosticInfo) ==
|
||||
@@ -120,25 +128,25 @@ static_assert(sizeof(storedDiagnosticInfos) / sizeof(StoredDiagnosticInfo) ==
|
||||
"array size mismatch");
|
||||
|
||||
static constexpr const char * const diagnosticStrings[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) Text,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) Text,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
"<not a diagnostic>",
|
||||
};
|
||||
|
||||
static constexpr const char *const debugDiagnosticStrings[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) Text " [" #ID "]",
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) Text " [" #ID "]",
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
"<not a diagnostic>",
|
||||
};
|
||||
|
||||
static constexpr const char *const diagnosticIDStrings[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) #ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) #ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
"<not a diagnostic>",
|
||||
};
|
||||
|
||||
static constexpr const char *const fixItStrings[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature)
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature)
|
||||
#define FIXIT(ID, Text, Signature) Text,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
"<not a fix-it>",
|
||||
@@ -171,6 +179,8 @@ static constexpr auto educationalNotes = _EducationalNotes.value;
|
||||
DiagnosticState::DiagnosticState() {
|
||||
// Initialize our ignored diagnostics to default
|
||||
ignoredDiagnostics.resize(LocalDiagID::NumDiags);
|
||||
// Initialize warningsAsErrors to default
|
||||
warningsAsErrors.resize(LocalDiagID::NumDiags);
|
||||
}
|
||||
|
||||
static CharSourceRange toCharSourceRange(SourceManager &SM, SourceRange SR) {
|
||||
@@ -509,6 +519,44 @@ bool DiagnosticEngine::finishProcessing() {
|
||||
return hadError;
|
||||
}
|
||||
|
||||
void DiagnosticEngine::setWarningsAsErrorsRules(
|
||||
const std::vector<WarningAsErrorRule> &rules) {
|
||||
std::vector<std::string> unknownGroups;
|
||||
for (const auto &rule : rules) {
|
||||
bool isEnabled = [&] {
|
||||
switch (rule.getAction()) {
|
||||
case WarningAsErrorRule::Action::Enable:
|
||||
return true;
|
||||
case WarningAsErrorRule::Action::Disable:
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
auto target = rule.getTarget();
|
||||
if (auto group = std::get_if<WarningAsErrorRule::TargetGroup>(&target)) {
|
||||
auto name = std::string_view(group->name);
|
||||
// Validate the group name and set the new behavior for each diagnostic
|
||||
// associated with the group and all its subgroups.
|
||||
if (auto groupID = getDiagGroupIDByName(name);
|
||||
groupID && *groupID != DiagGroupID::no_group) {
|
||||
getDiagGroupInfoByID(*groupID).traverseDepthFirst([&](auto group) {
|
||||
for (DiagID diagID : group.diagnostics) {
|
||||
state.setWarningAsErrorForDiagID(diagID, isEnabled);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
unknownGroups.push_back(std::string(name));
|
||||
}
|
||||
} else if (std::holds_alternative<WarningAsErrorRule::TargetAll>(target)) {
|
||||
state.setAllWarningsAsErrors(isEnabled);
|
||||
} else {
|
||||
llvm_unreachable("unhandled WarningAsErrorRule::Target");
|
||||
}
|
||||
}
|
||||
for (const auto &unknownGroup : unknownGroups) {
|
||||
diagnose(SourceLoc(), diag::unknown_warning_group, unknownGroup);
|
||||
}
|
||||
}
|
||||
|
||||
/// Skip forward to one of the given delimiters.
|
||||
///
|
||||
/// \param Text The text to search through, which will be updated to point
|
||||
@@ -1191,7 +1239,7 @@ DiagnosticBehavior DiagnosticState::determineBehavior(const Diagnostic &diag) {
|
||||
// 4) If the user substituted a different behavior for this behavior, apply
|
||||
// that change
|
||||
if (lvl == DiagnosticBehavior::Warning) {
|
||||
if (warningsAsErrors)
|
||||
if (getWarningAsErrorForDiagID(diag.getID()))
|
||||
lvl = DiagnosticBehavior::Error;
|
||||
if (suppressWarnings)
|
||||
lvl = DiagnosticBehavior::Ignore;
|
||||
|
||||
225
lib/AST/DiagnosticGroups.cpp
Normal file
225
lib/AST/DiagnosticGroups.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
//===--- DiagnosticGroups.cpp - Diagnostic Groups ---------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the diagnostic groups enumaration, group graph
|
||||
// and auxilary functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/AST/DiagnosticGroups.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace swift {
|
||||
|
||||
namespace {
|
||||
|
||||
template <size_t SupergroupsSize, size_t SubgroupsSize, size_t DiagnosticsSize>
|
||||
struct GroupConnections {
|
||||
std::array<DiagGroupID, SupergroupsSize> supergroups;
|
||||
std::array<DiagGroupID, SubgroupsSize> subgroups;
|
||||
std::array<DiagID, DiagnosticsSize> diagnostics;
|
||||
|
||||
constexpr GroupConnections(
|
||||
const std::array<DiagGroupID, SupergroupsSize> &supergroups,
|
||||
const std::array<DiagGroupID, SubgroupsSize> &subgroups,
|
||||
const std::array<DiagID, DiagnosticsSize> &diagnostics)
|
||||
: supergroups(supergroups), subgroups(subgroups),
|
||||
diagnostics(diagnostics) {}
|
||||
};
|
||||
|
||||
// This CTAD is needed in C++17 only. Remove after update to C++20.
|
||||
template <size_t SupergroupsSize, size_t SubgroupsSize, size_t DiagnosticsSize>
|
||||
GroupConnections(const std::array<DiagGroupID, SupergroupsSize> &,
|
||||
const std::array<DiagGroupID, SubgroupsSize> &,
|
||||
const std::array<DiagID, DiagnosticsSize> &)
|
||||
-> GroupConnections<SupergroupsSize, SubgroupsSize, DiagnosticsSize>;
|
||||
|
||||
constexpr const auto diagnosticGroupConnections = [] {
|
||||
constexpr auto sizes = [] {
|
||||
std::array<size_t, DiagGroupsCount> supergroupsCount{};
|
||||
std::array<size_t, DiagGroupsCount> subgroupsCount{};
|
||||
std::array<size_t, DiagGroupsCount> diagnosticsCount{};
|
||||
|
||||
// Count edges for each diagnostic group
|
||||
#define GROUP_LINK(Parent, Child) \
|
||||
subgroupsCount[(size_t)DiagGroupID::Parent]++; \
|
||||
supergroupsCount[(size_t)DiagGroupID::Child]++;
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
|
||||
// Count attached diagnostic IDs for each diagnostic group
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
diagnosticsCount[(size_t)DiagGroupID::Group]++;
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
|
||||
return std::tuple{supergroupsCount, subgroupsCount, diagnosticsCount};
|
||||
}();
|
||||
constexpr auto supergroupsCount = std::get<0>(sizes);
|
||||
constexpr auto subgroupsCount = std::get<1>(sizes);
|
||||
constexpr auto diagnosticsCount = std::get<2>(sizes);
|
||||
|
||||
// Declare all edges
|
||||
#define GROUP(Name, Version) \
|
||||
std::array<DiagGroupID, supergroupsCount[(size_t)DiagGroupID::Name]> \
|
||||
Name##_supergroups{}; \
|
||||
std::array<DiagGroupID, subgroupsCount[(size_t)DiagGroupID::Name]> \
|
||||
Name##_subgroups{}; \
|
||||
std::array<DiagID, diagnosticsCount[(size_t)DiagGroupID::Name]> \
|
||||
Name##_diagnostics{}; \
|
||||
[[maybe_unused]] size_t Name##_supergroupsIndex = 0; \
|
||||
[[maybe_unused]] size_t Name##_subgroupsIndex = 0; \
|
||||
[[maybe_unused]] size_t Name##_diagnosticsIndex = 0;
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
|
||||
// Bind all groups to each other
|
||||
#define GROUP_LINK(Parent, Child) \
|
||||
Parent##_subgroups[Parent##_subgroupsIndex++] = DiagGroupID::Child; \
|
||||
Child##_supergroups[Child##_supergroupsIndex++] = DiagGroupID::Parent;
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
|
||||
// Bind all diagnostics to their groups
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
Group##_diagnostics[Group##_diagnosticsIndex++] = DiagID::ID;
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
|
||||
// Produce the resulting structure with all the edges
|
||||
#define GROUP(Name, Version) \
|
||||
GroupConnections(Name##_supergroups, Name##_subgroups, Name##_diagnostics),
|
||||
return std::tuple{
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
}();
|
||||
|
||||
std::unordered_map<std::string_view, DiagGroupID> nameToIDMap{
|
||||
#define GROUP(Name, Version) {#Name, DiagGroupID::Name},
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
|
||||
void traverseDepthFirst(DiagGroupID id,
|
||||
std::unordered_set<DiagGroupID> &visited,
|
||||
llvm::function_ref<void(const DiagGroupInfo &)> func) {
|
||||
if (visited.insert(id).second) {
|
||||
const auto &info = getDiagGroupInfoByID(id);
|
||||
func(info);
|
||||
for (const auto subgroup : info.subgroups) {
|
||||
traverseDepthFirst(subgroup, visited, func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
constexpr const std::array<DiagGroupInfo, DiagGroupsCount> diagnosticGroupsInfo{
|
||||
#define GROUP(Name, Version) \
|
||||
DiagGroupInfo{ \
|
||||
DiagGroupID::Name, \
|
||||
#Name, \
|
||||
#Version, \
|
||||
llvm::ArrayRef<DiagGroupID>( \
|
||||
std::get<(size_t)DiagGroupID::Name>(diagnosticGroupConnections) \
|
||||
.supergroups), \
|
||||
llvm::ArrayRef<DiagGroupID>( \
|
||||
std::get<(size_t)DiagGroupID::Name>(diagnosticGroupConnections) \
|
||||
.subgroups), \
|
||||
llvm::ArrayRef<DiagID>( \
|
||||
std::get<(size_t)DiagGroupID::Name>(diagnosticGroupConnections) \
|
||||
.diagnostics)},
|
||||
#include "swift/AST/DiagnosticGroups.def"
|
||||
};
|
||||
|
||||
const DiagGroupInfo &getDiagGroupInfoByID(DiagGroupID id) {
|
||||
return diagnosticGroupsInfo[(size_t)id];
|
||||
}
|
||||
|
||||
std::optional<DiagGroupID> getDiagGroupIDByName(std::string_view name) {
|
||||
auto it = nameToIDMap.find(name);
|
||||
if (it == nameToIDMap.end())
|
||||
return std::nullopt;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void DiagGroupInfo::traverseDepthFirst(
|
||||
llvm::function_ref<void(const DiagGroupInfo &)> func) const {
|
||||
std::unordered_set<DiagGroupID> visited;
|
||||
::swift::traverseDepthFirst(id, visited, func);
|
||||
}
|
||||
|
||||
namespace validation {
|
||||
|
||||
template <typename F, size_t... Ints>
|
||||
constexpr void unfold(F &&function, std::index_sequence<Ints...>) {
|
||||
(function(std::integral_constant<size_t, Ints>{}), ...);
|
||||
}
|
||||
|
||||
template <size_t Size, typename F>
|
||||
constexpr void constexpr_for(F &&function) {
|
||||
unfold(function, std::make_index_sequence<Size>());
|
||||
}
|
||||
|
||||
template <size_t Group>
|
||||
constexpr bool
|
||||
hasCycleFromGroup(std::array<bool, DiagGroupsCount> &visited,
|
||||
std::array<bool, DiagGroupsCount> &recursionStack) {
|
||||
if (!visited[Group]) {
|
||||
visited[Group] = true;
|
||||
recursionStack[Group] = true;
|
||||
constexpr auto subgroups =
|
||||
std::get<Group>(diagnosticGroupConnections).subgroups;
|
||||
bool isCycleFound = false;
|
||||
constexpr_for<subgroups.size()>([&](auto i) {
|
||||
constexpr auto subgroup = (size_t)subgroups[i];
|
||||
if (!visited[subgroup] &&
|
||||
hasCycleFromGroup<subgroup>(visited, recursionStack))
|
||||
isCycleFound = true;
|
||||
else if (recursionStack[subgroup])
|
||||
isCycleFound = true;
|
||||
});
|
||||
if (isCycleFound)
|
||||
return true;
|
||||
}
|
||||
recursionStack[Group] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool hasCycle() {
|
||||
std::array<bool, DiagGroupsCount> recursionStack{};
|
||||
std::array<bool, DiagGroupsCount> visited{};
|
||||
bool isCycleFound = false;
|
||||
constexpr_for<DiagGroupsCount>([&](auto i) {
|
||||
if (!visited[i] && hasCycleFromGroup<i>(visited, recursionStack))
|
||||
isCycleFound = true;
|
||||
});
|
||||
return isCycleFound;
|
||||
}
|
||||
|
||||
template <DiagGroupID Child, DiagGroupID Parent>
|
||||
constexpr bool isGroupInSupergroup() {
|
||||
for (const auto group :
|
||||
std::get<(size_t)Child>(diagnosticGroupConnections).supergroups)
|
||||
if (group == Parent)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static_assert(!hasCycle(), "Diagnostic groups graph has a cycle!");
|
||||
// Sanity check for the "no_group" group
|
||||
static_assert((uint16_t)DiagGroupID::no_group == 0, "0 isn't no_group");
|
||||
static_assert(std::get<0>(diagnosticGroupConnections).supergroups.size() == 0,
|
||||
"no_group isn't a top-level group");
|
||||
static_assert(std::get<0>(diagnosticGroupConnections).subgroups.size() == 0,
|
||||
"no_group shouldn't have subgroups");
|
||||
// Check groups have expected supergroups
|
||||
static_assert(isGroupInSupergroup<DiagGroupID::availability_deprecated,
|
||||
DiagGroupID::deprecated>());
|
||||
|
||||
} // end namespace validation
|
||||
|
||||
} // end namespace swift
|
||||
@@ -14,29 +14,17 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/AST/DiagnosticList.h"
|
||||
#include "swift/AST/DiagnosticsCommon.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
using namespace swift;
|
||||
|
||||
enum class swift::DiagID : uint32_t {
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
static_assert(static_cast<uint32_t>(swift::DiagID::invalid_diagnostic) == 0,
|
||||
"0 is not the invalid diagnostic ID");
|
||||
|
||||
enum class swift::FixItID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature)
|
||||
#define FIXIT(ID, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
// Define all of the diagnostic objects and initialize them with their
|
||||
// diagnostic IDs.
|
||||
namespace swift {
|
||||
namespace diag {
|
||||
#define DIAG(KIND,ID,Options,Text,Signature) \
|
||||
detail::DiagWithArguments<void Signature>::type ID = { DiagID::ID };
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
detail::DiagWithArguments<void Signature>::type ID = {DiagID::ID};
|
||||
#define FIXIT(ID, Text, Signature) \
|
||||
detail::StructuredFixItWithArguments<void Signature>::type ID = {FixItID::ID};
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
|
||||
@@ -311,8 +311,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
|
||||
inputArgs.AddLastArg(arguments, options::OPT_profile_generate);
|
||||
inputArgs.AddLastArg(arguments, options::OPT_profile_use);
|
||||
inputArgs.AddLastArg(arguments, options::OPT_profile_coverage_mapping);
|
||||
inputArgs.AddAllArgs(arguments, options::OPT_warnings_as_errors,
|
||||
options::OPT_no_warnings_as_errors);
|
||||
inputArgs.AddAllArgs(arguments, options::OPT_warning_treating_Group);
|
||||
inputArgs.AddLastArg(arguments, options::OPT_sanitize_EQ);
|
||||
inputArgs.AddLastArg(arguments, options::OPT_sanitize_recover_EQ);
|
||||
inputArgs.AddLastArg(arguments,
|
||||
|
||||
@@ -2261,9 +2261,24 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||
Opts.FixitCodeForAllDiagnostics |= Args.hasArg(OPT_fixit_all);
|
||||
Opts.SuppressWarnings |= Args.hasArg(OPT_suppress_warnings);
|
||||
Opts.SuppressRemarks |= Args.hasArg(OPT_suppress_remarks);
|
||||
Opts.WarningsAsErrors = Args.hasFlag(options::OPT_warnings_as_errors,
|
||||
options::OPT_no_warnings_as_errors,
|
||||
false);
|
||||
for (const Arg *arg : Args.filtered(OPT_warning_treating_Group)) {
|
||||
Opts.WarningsAsErrorsRules.push_back([&] {
|
||||
switch (arg->getOption().getID()) {
|
||||
case OPT_warnings_as_errors:
|
||||
return WarningAsErrorRule(WarningAsErrorRule::Action::Enable);
|
||||
case OPT_no_warnings_as_errors:
|
||||
return WarningAsErrorRule(WarningAsErrorRule::Action::Disable);
|
||||
case OPT_warning_as_error:
|
||||
return WarningAsErrorRule(WarningAsErrorRule::Action::Enable,
|
||||
arg->getValue());
|
||||
case OPT_no_warning_as_error:
|
||||
return WarningAsErrorRule(WarningAsErrorRule::Action::Disable,
|
||||
arg->getValue());
|
||||
default:
|
||||
llvm_unreachable("unhandled warning as error option");
|
||||
}
|
||||
}());
|
||||
}
|
||||
Opts.PrintDiagnosticNames |= Args.hasArg(OPT_debug_diagnostic_names);
|
||||
Opts.PrintEducationalNotes |= Args.hasArg(OPT_print_educational_notes);
|
||||
if (Arg *A = Args.getLastArg(OPT_diagnostic_documentation_path)) {
|
||||
@@ -2306,8 +2321,6 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
||||
Opts.LocalizationPath = A->getValue();
|
||||
}
|
||||
}
|
||||
assert(!(Opts.WarningsAsErrors && Opts.SuppressWarnings) &&
|
||||
"conflicting arguments; should have been caught by driver");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -723,9 +723,8 @@ void CompilerInstance::setUpDiagnosticOptions() {
|
||||
if (Invocation.getDiagnosticOptions().SuppressRemarks) {
|
||||
Diagnostics.setSuppressRemarks(true);
|
||||
}
|
||||
if (Invocation.getDiagnosticOptions().WarningsAsErrors) {
|
||||
Diagnostics.setWarningsAsErrors(true);
|
||||
}
|
||||
Diagnostics.setWarningsAsErrorsRules(
|
||||
Invocation.getDiagnosticOptions().WarningsAsErrorsRules);
|
||||
if (Invocation.getDiagnosticOptions().PrintDiagnosticNames) {
|
||||
Diagnostics.setPrintDiagnosticNames(true);
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
namespace {
|
||||
|
||||
enum LocalDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
NumDiags
|
||||
};
|
||||
|
||||
static constexpr const char *const diagnosticNameStrings[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) " [" #ID "]",
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) " [" #ID "]",
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
"<not a diagnostic>",
|
||||
};
|
||||
@@ -206,7 +206,7 @@ void StringsLocalizationProducer::forEachAvailable(
|
||||
void StringsLocalizationProducer::readStringsFile(
|
||||
llvm::MemoryBuffer *in, std::vector<std::string> &diagnostics) {
|
||||
std::map<std::string, unsigned> diagLocs;
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) \
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) \
|
||||
diagLocs[#ID] = static_cast<unsigned>(LocalDiagID::ID);
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
#undef DIAG
|
||||
|
||||
50
test/diagnostics/warnings_as_errors_rules.swift
Normal file
50
test/diagnostics/warnings_as_errors_rules.swift
Normal file
@@ -0,0 +1,50 @@
|
||||
// RUN: not %target-swift-frontend -typecheck -diagnostic-style llvm -warnings-as-errors %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-ALL
|
||||
// RUN: not %target-swift-frontend -typecheck -diagnostic-style llvm -warning-as-error availability_deprecated %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-GROUP
|
||||
// RUN: not %target-swift-frontend -typecheck -diagnostic-style llvm -warning-as-error deprecated %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-SUPERGROUP
|
||||
// RUN: %target-swift-frontend -typecheck -diagnostic-style llvm -warnings-as-errors -no-warnings-as-errors %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-ALL-NWAE-ALL
|
||||
// RUN: %target-swift-frontend -typecheck -diagnostic-style llvm -warnings-as-errors -no-warning-as-error availability_deprecated %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-ALL-NWAE-GROUP
|
||||
// RUN: %target-swift-frontend -typecheck -diagnostic-style llvm -warnings-as-errors -no-warning-as-error deprecated %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-ALL-NWAE-SUPERGROUP
|
||||
// RUN: %target-swift-frontend -typecheck -diagnostic-style llvm -warning-as-error deprecated -no-warning-as-error availability_deprecated %s 2>&1 | %FileCheck %s --check-prefix=CHECK-WAE-SUPERGROUP-NWAE-GROUP
|
||||
|
||||
|
||||
@available(*, deprecated)
|
||||
func foo() {
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "bar2")
|
||||
func bar() {
|
||||
}
|
||||
|
||||
|
||||
// CHECK-WAE-ALL: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NOT: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-GROUP: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-GROUP-NOT: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-SUPERGROUP: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-SUPERGROUP-NOT: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-ALL: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-ALL-NOT: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-GROUP: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-GROUP-NOT: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-SUPERGROUP: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-ALL-NWAE-SUPERGROUP-NOT: error: 'foo()' is deprecated
|
||||
// CHECK-WAE-SUPERGROUP-NWAE-GROUP: warning: 'foo()' is deprecated
|
||||
// CHECK-WAE-SUPERGROUP-NWAE-GROUP-NOT: error: 'foo()' is deprecated
|
||||
foo()
|
||||
|
||||
|
||||
// CHECK-WAE-ALL: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NOT: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-GROUP: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-GROUP-NOT: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-SUPERGROUP: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-SUPERGROUP-NOT: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-ALL: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-ALL-NOT: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-GROUP: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-GROUP-NOT: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-SUPERGROUP: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-ALL-NWAE-SUPERGROUP-NOT: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-SUPERGROUP-NWAE-GROUP: warning: 'bar()' is deprecated: renamed to 'bar2'
|
||||
// CHECK-WAE-SUPERGROUP-NWAE-GROUP-NOT: error: 'bar()' is deprecated: renamed to 'bar2'
|
||||
bar()
|
||||
@@ -32,17 +32,17 @@
|
||||
#include <system_error>
|
||||
|
||||
static constexpr const char *const diagnosticID[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) #ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) #ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
static constexpr const char *const diagnosticMessages[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) Text,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) Text,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
enum LocalDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
NumDiags
|
||||
};
|
||||
|
||||
@@ -34,18 +34,18 @@ namespace swift {
|
||||
namespace unittests {
|
||||
|
||||
enum LocalDiagID : uint32_t {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
NumDiags
|
||||
};
|
||||
|
||||
static constexpr const char *const diagnosticID[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) #ID,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) #ID,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
static constexpr const char *const diagnosticMessages[] = {
|
||||
#define DIAG(KIND, ID, Options, Text, Signature) Text,
|
||||
#define DIAG(KIND, ID, Group, Options, Text, Signature) Text,
|
||||
#include "swift/AST/DiagnosticsAll.def"
|
||||
};
|
||||
|
||||
|
||||
30
userdocs/diagnostic_groups/availability_deprecated.md
Normal file
30
userdocs/diagnostic_groups/availability_deprecated.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Availability Deprecation Warnings (`availability_deprecated`)
|
||||
|
||||
This diagnostic group includes warnings related to deprecated APIs that may be removed in future versions and should be replaced with more current alternatives.
|
||||
|
||||
The `availability_deprecated` group covers the following warnings:
|
||||
- Use of a function annotated with `@available(<platform>, deprecated: <version>)`
|
||||
```swift
|
||||
@available(iOS, deprecated: 10.0)
|
||||
func oldFunction() {
|
||||
// This function is deprecated and should not be used.
|
||||
}
|
||||
|
||||
oldFunction() // 'oldFunction()' is deprecated
|
||||
```
|
||||
- Use of a function annotated with `@available(<platform>, deprecated: <version>, renamed: "<new name>")`
|
||||
```swift
|
||||
@available(iOS, deprecated: 10.0, renamed: "newFunction")
|
||||
func oldFunction() {
|
||||
// This function is deprecated and should not be used.
|
||||
}
|
||||
|
||||
oldFunction() // 'oldFunction()' is deprecated: renamed to 'newFunction'
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
```sh
|
||||
swiftc -warning-as-error availability_deprecated file.swift
|
||||
swiftc -warnings-as-errors -no-warning-as-error availability_deprecated file.swift
|
||||
```
|
||||
12
userdocs/diagnostic_groups/deprecated.md
Normal file
12
userdocs/diagnostic_groups/deprecated.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Deprecation Warnings (`deprecated`)
|
||||
|
||||
The deprecated group is a supergroup designed to manage all kinds of warnings related to the use of deprecated elements. This group can include other diagnostic groups with similar meanings. The deprecated group includes the following groups:
|
||||
|
||||
- `availability_deprecated`: Includes warnings for APIs marked as deprecated.
|
||||
|
||||
## Usage Example
|
||||
|
||||
```sh
|
||||
swiftc -warning-as-error deprecated file.swift
|
||||
swiftc -warnings-as-errors -no-warning-as-error deprecated file.swift
|
||||
```
|
||||
15
userdocs/diagnostic_groups/unknown_warning_group.md
Normal file
15
userdocs/diagnostic_groups/unknown_warning_group.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Unknown "Warning Group" Warnings (`unknown_warning_group`)
|
||||
|
||||
The `unknown_warning_group` diagnostic group addresses warnings related to the specification of unrecognized warning groups in compilation flags.
|
||||
|
||||
```sh
|
||||
swiftc -warning-as-error non_existing_group file.swift
|
||||
<unknown>:0: warning: unknown warning group: 'non_existing_group'
|
||||
```
|
||||
|
||||
Such warnings are emitted after the behavior for all specified warning groups has been processed, which means their behavior can also be specified. For example:
|
||||
|
||||
```sh
|
||||
swiftc -warning-as-error unknown_warning_group -warning-as-error non_existing_group file.swift
|
||||
<unknown>:0: error: unknown warning group: 'non_existing_group'
|
||||
```
|
||||
Reference in New Issue
Block a user