File indexing completed on 2026-05-10 08:36:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
0015 #define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
0016
0017 #include "clang/Basic/DiagnosticCategories.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/Support/ErrorHandling.h"
0022 #include <optional>
0023 #include <vector>
0024
0025 namespace clang {
0026 class DiagnosticsEngine;
0027 class DiagnosticBuilder;
0028 class SourceLocation;
0029
0030
0031 namespace diag {
0032 enum class Group;
0033
0034
0035 enum {
0036 DIAG_SIZE_COMMON = 300,
0037 DIAG_SIZE_DRIVER = 400,
0038 DIAG_SIZE_FRONTEND = 200,
0039 DIAG_SIZE_SERIALIZATION = 120,
0040 DIAG_SIZE_LEX = 400,
0041 DIAG_SIZE_PARSE = 700,
0042 DIAG_SIZE_AST = 300,
0043 DIAG_SIZE_COMMENT = 100,
0044 DIAG_SIZE_CROSSTU = 100,
0045 DIAG_SIZE_SEMA = 5000,
0046 DIAG_SIZE_ANALYSIS = 100,
0047 DIAG_SIZE_REFACTORING = 1000,
0048 DIAG_SIZE_INSTALLAPI = 100,
0049 };
0050
0051 enum {
0052 DIAG_START_COMMON = 0,
0053 DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
0054 DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
0055 DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
0056 DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
0057 DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
0058 DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
0059 DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
0060 DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
0061 DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
0062 DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
0063 DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
0064 DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
0065 DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
0066 };
0067
0068 class CustomDiagInfo;
0069
0070
0071 typedef unsigned kind;
0072
0073
0074 enum {
0075 #define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \
0076 NOWERROR, SHOWINSYSHEADER, SHOWINSYSMACRO, DEFFERABLE) \
0077 ENUM,
0078 #define COMMONSTART
0079 #include "clang/Basic/DiagnosticCommonKinds.inc"
0080 NUM_BUILTIN_COMMON_DIAGNOSTICS
0081 #undef DIAG
0082 };
0083
0084
0085
0086
0087
0088 enum class Severity : uint8_t {
0089
0090 Ignored = 1,
0091 Remark = 2,
0092 Warning = 3,
0093 Error = 4,
0094 Fatal = 5
0095 };
0096
0097
0098
0099 enum class Flavor {
0100 WarningOrError,
0101
0102 Remark
0103
0104 };
0105 }
0106
0107 class DiagnosticMapping {
0108 LLVM_PREFERRED_TYPE(diag::Severity)
0109 unsigned Severity : 3;
0110 LLVM_PREFERRED_TYPE(bool)
0111 unsigned IsUser : 1;
0112 LLVM_PREFERRED_TYPE(bool)
0113 unsigned IsPragma : 1;
0114 LLVM_PREFERRED_TYPE(bool)
0115 unsigned HasNoWarningAsError : 1;
0116 LLVM_PREFERRED_TYPE(bool)
0117 unsigned HasNoErrorAsFatal : 1;
0118 LLVM_PREFERRED_TYPE(bool)
0119 unsigned WasUpgradedFromWarning : 1;
0120
0121 public:
0122 static DiagnosticMapping Make(diag::Severity Severity, bool IsUser,
0123 bool IsPragma) {
0124 DiagnosticMapping Result;
0125 Result.Severity = (unsigned)Severity;
0126 Result.IsUser = IsUser;
0127 Result.IsPragma = IsPragma;
0128 Result.HasNoWarningAsError = 0;
0129 Result.HasNoErrorAsFatal = 0;
0130 Result.WasUpgradedFromWarning = 0;
0131 return Result;
0132 }
0133
0134 diag::Severity getSeverity() const { return (diag::Severity)Severity; }
0135 void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; }
0136
0137 bool isUser() const { return IsUser; }
0138 bool isPragma() const { return IsPragma; }
0139
0140 bool isErrorOrFatal() const {
0141 return getSeverity() == diag::Severity::Error ||
0142 getSeverity() == diag::Severity::Fatal;
0143 }
0144
0145 bool hasNoWarningAsError() const { return HasNoWarningAsError; }
0146 void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
0147
0148 bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
0149 void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
0150
0151
0152
0153
0154 bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; }
0155 void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; }
0156
0157
0158 unsigned serialize() const {
0159 return (IsUser << 7) | (IsPragma << 6) | (HasNoWarningAsError << 5) |
0160 (HasNoErrorAsFatal << 4) | (WasUpgradedFromWarning << 3) | Severity;
0161 }
0162
0163 static DiagnosticMapping deserialize(unsigned Bits) {
0164 DiagnosticMapping Result;
0165 Result.IsUser = (Bits >> 7) & 1;
0166 Result.IsPragma = (Bits >> 6) & 1;
0167 Result.HasNoWarningAsError = (Bits >> 5) & 1;
0168 Result.HasNoErrorAsFatal = (Bits >> 4) & 1;
0169 Result.WasUpgradedFromWarning = (Bits >> 3) & 1;
0170 Result.Severity = Bits & 0x7;
0171 return Result;
0172 }
0173
0174 bool operator==(DiagnosticMapping Other) const {
0175 return serialize() == Other.serialize();
0176 }
0177 };
0178
0179
0180
0181
0182 class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
0183 public:
0184
0185 enum Level : uint8_t { Ignored, Note, Remark, Warning, Error, Fatal };
0186
0187
0188 enum Class {
0189 CLASS_INVALID = 0x00,
0190 CLASS_NOTE = 0x01,
0191 CLASS_REMARK = 0x02,
0192 CLASS_WARNING = 0x03,
0193 CLASS_EXTENSION = 0x04,
0194 CLASS_ERROR = 0x05
0195 };
0196
0197 static bool IsCustomDiag(diag::kind Diag) {
0198 return Diag >= diag::DIAG_UPPER_LIMIT;
0199 }
0200
0201 class CustomDiagDesc {
0202 LLVM_PREFERRED_TYPE(diag::Severity)
0203 unsigned DefaultSeverity : 3;
0204 LLVM_PREFERRED_TYPE(Class)
0205 unsigned DiagClass : 3;
0206 LLVM_PREFERRED_TYPE(bool)
0207 unsigned ShowInSystemHeader : 1;
0208 LLVM_PREFERRED_TYPE(bool)
0209 unsigned ShowInSystemMacro : 1;
0210 LLVM_PREFERRED_TYPE(bool)
0211 unsigned HasGroup : 1;
0212 diag::Group Group;
0213 std::string Description;
0214
0215 auto get_as_tuple() const {
0216 return std::tuple(DefaultSeverity, DiagClass, ShowInSystemHeader,
0217 ShowInSystemMacro, HasGroup, Group,
0218 std::string_view{Description});
0219 }
0220
0221 public:
0222 CustomDiagDesc(diag::Severity DefaultSeverity, std::string Description,
0223 unsigned Class = CLASS_WARNING,
0224 bool ShowInSystemHeader = false,
0225 bool ShowInSystemMacro = false,
0226 std::optional<diag::Group> Group = std::nullopt)
0227 : DefaultSeverity(static_cast<unsigned>(DefaultSeverity)),
0228 DiagClass(Class), ShowInSystemHeader(ShowInSystemHeader),
0229 ShowInSystemMacro(ShowInSystemMacro), HasGroup(Group != std::nullopt),
0230 Group(Group.value_or(diag::Group{})),
0231 Description(std::move(Description)) {}
0232
0233 std::optional<diag::Group> GetGroup() const {
0234 if (HasGroup)
0235 return Group;
0236 return std::nullopt;
0237 }
0238
0239 diag::Severity GetDefaultSeverity() const {
0240 return static_cast<diag::Severity>(DefaultSeverity);
0241 }
0242
0243 Class GetClass() const { return static_cast<Class>(DiagClass); }
0244 std::string_view GetDescription() const { return Description; }
0245 bool ShouldShowInSystemHeader() const { return ShowInSystemHeader; }
0246
0247 friend bool operator==(const CustomDiagDesc &lhs,
0248 const CustomDiagDesc &rhs) {
0249 return lhs.get_as_tuple() == rhs.get_as_tuple();
0250 }
0251
0252 friend bool operator<(const CustomDiagDesc &lhs,
0253 const CustomDiagDesc &rhs) {
0254 return lhs.get_as_tuple() < rhs.get_as_tuple();
0255 }
0256 };
0257
0258 struct GroupInfo {
0259 LLVM_PREFERRED_TYPE(diag::Severity)
0260 unsigned Severity : 3;
0261 LLVM_PREFERRED_TYPE(bool)
0262 unsigned HasNoWarningAsError : 1;
0263 };
0264
0265 private:
0266
0267 std::unique_ptr<diag::CustomDiagInfo> CustomDiagInfo;
0268 std::unique_ptr<GroupInfo[]> GroupInfos = []() {
0269 auto GIs = std::make_unique<GroupInfo[]>(
0270 static_cast<size_t>(diag::Group::NUM_GROUPS));
0271 for (size_t i = 0; i != static_cast<size_t>(diag::Group::NUM_GROUPS); ++i)
0272 GIs[i] = {{}, false};
0273 return GIs;
0274 }();
0275
0276 public:
0277 DiagnosticIDs();
0278 ~DiagnosticIDs();
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 unsigned getCustomDiagID(CustomDiagDesc Diag);
0290
0291
0292
0293 unsigned getCustomDiagID(Level Level, StringRef Message) {
0294 return getCustomDiagID([&]() -> CustomDiagDesc {
0295 switch (Level) {
0296 case DiagnosticIDs::Level::Ignored:
0297 return {diag::Severity::Ignored, std::string(Message), CLASS_WARNING,
0298 true, true};
0299 case DiagnosticIDs::Level::Note:
0300 return {diag::Severity::Fatal, std::string(Message), CLASS_NOTE,
0301 true, true};
0302 case DiagnosticIDs::Level::Remark:
0303 return {diag::Severity::Remark, std::string(Message), CLASS_REMARK,
0304 true, true};
0305 case DiagnosticIDs::Level::Warning:
0306 return {diag::Severity::Warning, std::string(Message), CLASS_WARNING,
0307 true, true};
0308 case DiagnosticIDs::Level::Error:
0309 return {diag::Severity::Error, std::string(Message), CLASS_ERROR,
0310 true, true};
0311 case DiagnosticIDs::Level::Fatal:
0312 return {diag::Severity::Fatal, std::string(Message), CLASS_ERROR,
0313 true, true};
0314 }
0315 llvm_unreachable("Fully covered switch above!");
0316 }());
0317 }
0318
0319
0320
0321
0322
0323
0324 StringRef getDescription(unsigned DiagID) const;
0325
0326
0327
0328
0329
0330 bool isWarningOrExtension(unsigned DiagID) const;
0331
0332
0333
0334 bool isDefaultMappingAsError(unsigned DiagID) const;
0335
0336
0337 DiagnosticMapping getDefaultMapping(unsigned DiagID) const;
0338
0339 void initCustomDiagMapping(DiagnosticMapping &, unsigned DiagID);
0340
0341
0342 bool isNote(unsigned DiagID) const;
0343
0344
0345
0346 bool isExtensionDiag(unsigned DiagID) const {
0347 bool ignored;
0348 return isExtensionDiag(DiagID, ignored);
0349 }
0350
0351
0352
0353
0354
0355
0356
0357
0358 bool isExtensionDiag(unsigned DiagID, bool &EnabledByDefault) const;
0359
0360
0361
0362
0363 static StringRef getWarningOptionForGroup(diag::Group);
0364
0365
0366 static StringRef getWarningOptionDocumentation(diag::Group GroupID);
0367
0368 void setGroupSeverity(StringRef Group, diag::Severity);
0369 void setGroupNoWarningsAsError(StringRef Group, bool);
0370
0371
0372
0373
0374 static std::optional<diag::Group> getGroupForWarningOption(StringRef);
0375
0376
0377 std::optional<diag::Group> getGroupForDiag(unsigned DiagID) const;
0378
0379
0380
0381
0382
0383 StringRef getWarningOptionForDiag(unsigned DiagID);
0384
0385
0386
0387 static unsigned getCategoryNumberForDiag(unsigned DiagID);
0388
0389
0390 static unsigned getNumberOfCategories();
0391
0392
0393 static StringRef getCategoryNameFromID(unsigned CategoryID);
0394
0395
0396
0397 static bool isARCDiagnostic(unsigned DiagID);
0398
0399
0400 static bool isCodegenABICheckDiagnostic(unsigned DiagID);
0401
0402
0403
0404 enum SFINAEResponse {
0405
0406
0407
0408
0409
0410 SFINAE_SubstitutionFailure,
0411
0412
0413
0414
0415 SFINAE_Suppress,
0416
0417
0418
0419
0420
0421 SFINAE_Report,
0422
0423
0424
0425 SFINAE_AccessControl
0426 };
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
0437
0438
0439
0440
0441
0442
0443 static bool isDeferrable(unsigned DiagID);
0444
0445
0446
0447
0448
0449
0450 static std::vector<std::string> getDiagnosticFlags();
0451
0452
0453
0454
0455
0456 bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
0457 SmallVectorImpl<diag::kind> &Diags) const;
0458
0459
0460 static void getAllDiagnostics(diag::Flavor Flavor,
0461 std::vector<diag::kind> &Diags);
0462
0463
0464
0465 static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
0466
0467 private:
0468
0469
0470
0471
0472
0473
0474
0475
0476 DiagnosticIDs::Level
0477 getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
0478 const DiagnosticsEngine &Diag) const LLVM_READONLY;
0479
0480 diag::Severity
0481 getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
0482 const DiagnosticsEngine &Diag) const LLVM_READONLY;
0483
0484 Class getDiagClass(unsigned DiagID) const;
0485
0486
0487
0488
0489
0490 bool ProcessDiag(DiagnosticsEngine &Diag,
0491 const DiagnosticBuilder &DiagBuilder) const;
0492
0493
0494
0495 void EmitDiag(DiagnosticsEngine &Diag, const DiagnosticBuilder &DiagBuilder,
0496 Level DiagLevel) const;
0497
0498
0499
0500 bool isUnrecoverable(unsigned DiagID) const;
0501
0502 friend class DiagnosticsEngine;
0503 };
0504
0505 }
0506
0507 #endif