1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the Diagnostic IDs-related interfaces. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Basic/DiagnosticIDs.h" 14 #include "clang/Basic/AllDiagnostics.h" 15 #include "clang/Basic/DiagnosticCategories.h" 16 #include "clang/Basic/SourceManager.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringTable.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/Path.h" 22 #include <map> 23 #include <optional> 24 using namespace clang; 25 26 //===----------------------------------------------------------------------===// 27 // Builtin Diagnostic information 28 //===----------------------------------------------------------------------===// 29 30 namespace { 31 32 struct StaticDiagInfoRec; 33 34 // Store the descriptions in a separate table to avoid pointers that need to 35 // be relocated, and also decrease the amount of data needed on 64-bit 36 // platforms. See "How To Write Shared Libraries" by Ulrich Drepper. 37 struct StaticDiagInfoDescriptionStringTable { 38 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 39 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 40 char ENUM##_desc[sizeof(DESC)]; 41 #include "clang/Basic/AllDiagnosticKinds.inc" 42 #undef DIAG 43 }; 44 45 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = { 46 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 47 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 48 DESC, 49 #include "clang/Basic/AllDiagnosticKinds.inc" 50 #undef DIAG 51 }; 52 53 extern const StaticDiagInfoRec StaticDiagInfo[]; 54 55 // Stored separately from StaticDiagInfoRec to pack better. Otherwise, 56 // StaticDiagInfoRec would have extra padding on 64-bit platforms. 57 const uint32_t StaticDiagInfoDescriptionOffsets[] = { 58 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 59 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 60 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc), 61 #include "clang/Basic/AllDiagnosticKinds.inc" 62 #undef DIAG 63 }; 64 65 enum DiagnosticClass { 66 CLASS_NOTE = DiagnosticIDs::CLASS_NOTE, 67 CLASS_REMARK = DiagnosticIDs::CLASS_REMARK, 68 CLASS_WARNING = DiagnosticIDs::CLASS_WARNING, 69 CLASS_EXTENSION = DiagnosticIDs::CLASS_EXTENSION, 70 CLASS_ERROR = DiagnosticIDs::CLASS_ERROR, 71 }; 72 73 struct StaticDiagInfoRec { 74 uint16_t DiagID; 75 LLVM_PREFERRED_TYPE(diag::Severity) 76 uint8_t DefaultSeverity : 3; 77 LLVM_PREFERRED_TYPE(DiagnosticClass) 78 uint8_t Class : 3; 79 LLVM_PREFERRED_TYPE(DiagnosticIDs::SFINAEResponse) 80 uint8_t SFINAE : 2; 81 uint8_t Category : 6; 82 LLVM_PREFERRED_TYPE(bool) 83 uint8_t WarnNoWerror : 1; 84 LLVM_PREFERRED_TYPE(bool) 85 uint8_t WarnShowInSystemHeader : 1; 86 LLVM_PREFERRED_TYPE(bool) 87 uint8_t WarnShowInSystemMacro : 1; 88 89 uint16_t OptionGroupIndex : 15; 90 LLVM_PREFERRED_TYPE(bool) 91 uint16_t Deferrable : 1; 92 93 uint16_t DescriptionLen; 94 95 unsigned getOptionGroupIndex() const { 96 return OptionGroupIndex; 97 } 98 99 StringRef getDescription() const { 100 size_t MyIndex = this - &StaticDiagInfo[0]; 101 uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex]; 102 const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions); 103 return StringRef(&Table[StringOffset], DescriptionLen); 104 } 105 106 diag::Flavor getFlavor() const { 107 return Class == CLASS_REMARK ? diag::Flavor::Remark 108 : diag::Flavor::WarningOrError; 109 } 110 111 bool operator<(const StaticDiagInfoRec &RHS) const { 112 return DiagID < RHS.DiagID; 113 } 114 }; 115 116 #define STRINGIFY_NAME(NAME) #NAME 117 #define VALIDATE_DIAG_SIZE(NAME) \ 118 static_assert( \ 119 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ 120 static_cast<unsigned>(diag::DIAG_START_##NAME) + \ 121 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \ 122 STRINGIFY_NAME( \ 123 DIAG_SIZE_##NAME) " is insufficient to contain all " \ 124 "diagnostics, it may need to be made larger in " \ 125 "DiagnosticIDs.h."); 126 VALIDATE_DIAG_SIZE(COMMON) 127 VALIDATE_DIAG_SIZE(DRIVER) 128 VALIDATE_DIAG_SIZE(FRONTEND) 129 VALIDATE_DIAG_SIZE(SERIALIZATION) 130 VALIDATE_DIAG_SIZE(LEX) 131 VALIDATE_DIAG_SIZE(PARSE) 132 VALIDATE_DIAG_SIZE(AST) 133 VALIDATE_DIAG_SIZE(COMMENT) 134 VALIDATE_DIAG_SIZE(CROSSTU) 135 VALIDATE_DIAG_SIZE(SEMA) 136 VALIDATE_DIAG_SIZE(ANALYSIS) 137 VALIDATE_DIAG_SIZE(REFACTORING) 138 VALIDATE_DIAG_SIZE(INSTALLAPI) 139 #undef VALIDATE_DIAG_SIZE 140 #undef STRINGIFY_NAME 141 142 const StaticDiagInfoRec StaticDiagInfo[] = { 143 // clang-format off 144 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 145 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 146 { \ 147 diag::ENUM, \ 148 DEFAULT_SEVERITY, \ 149 CLASS, \ 150 DiagnosticIDs::SFINAE, \ 151 CATEGORY, \ 152 NOWERROR, \ 153 SHOWINSYSHEADER, \ 154 SHOWINSYSMACRO, \ 155 GROUP, \ 156 DEFERRABLE, \ 157 STR_SIZE(DESC, uint16_t)}, 158 #include "clang/Basic/DiagnosticCommonKinds.inc" 159 #include "clang/Basic/DiagnosticDriverKinds.inc" 160 #include "clang/Basic/DiagnosticFrontendKinds.inc" 161 #include "clang/Basic/DiagnosticSerializationKinds.inc" 162 #include "clang/Basic/DiagnosticLexKinds.inc" 163 #include "clang/Basic/DiagnosticParseKinds.inc" 164 #include "clang/Basic/DiagnosticASTKinds.inc" 165 #include "clang/Basic/DiagnosticCommentKinds.inc" 166 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 167 #include "clang/Basic/DiagnosticSemaKinds.inc" 168 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 169 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 170 #include "clang/Basic/DiagnosticInstallAPIKinds.inc" 171 // clang-format on 172 #undef DIAG 173 }; 174 175 } // namespace 176 177 static const unsigned StaticDiagInfoSize = std::size(StaticDiagInfo); 178 179 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 180 /// or null if the ID is invalid. 181 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 182 // Out of bounds diag. Can't be in the table. 183 using namespace diag; 184 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) 185 return nullptr; 186 187 // Compute the index of the requested diagnostic in the static table. 188 // 1. Add the number of diagnostics in each category preceding the 189 // diagnostic and of the category the diagnostic is in. This gives us 190 // the offset of the category in the table. 191 // 2. Subtract the number of IDs in each category from our ID. This gives us 192 // the offset of the diagnostic in the category. 193 // This is cheaper than a binary search on the table as it doesn't touch 194 // memory at all. 195 unsigned Offset = 0; 196 unsigned ID = DiagID - DIAG_START_COMMON - 1; 197 #define CATEGORY(NAME, PREV) \ 198 if (DiagID > DIAG_START_##NAME) { \ 199 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ 200 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ 201 } 202 CATEGORY(DRIVER, COMMON) 203 CATEGORY(FRONTEND, DRIVER) 204 CATEGORY(SERIALIZATION, FRONTEND) 205 CATEGORY(LEX, SERIALIZATION) 206 CATEGORY(PARSE, LEX) 207 CATEGORY(AST, PARSE) 208 CATEGORY(COMMENT, AST) 209 CATEGORY(CROSSTU, COMMENT) 210 CATEGORY(SEMA, CROSSTU) 211 CATEGORY(ANALYSIS, SEMA) 212 CATEGORY(REFACTORING, ANALYSIS) 213 CATEGORY(INSTALLAPI, REFACTORING) 214 #undef CATEGORY 215 216 // Avoid out of bounds reads. 217 if (ID + Offset >= StaticDiagInfoSize) 218 return nullptr; 219 220 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); 221 222 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset]; 223 // If the diag id doesn't match we found a different diag, abort. This can 224 // happen when this function is called with an ID that points into a hole in 225 // the diagID space. 226 if (Found->DiagID != DiagID) 227 return nullptr; 228 return Found; 229 } 230 231 //===----------------------------------------------------------------------===// 232 // Custom Diagnostic information 233 //===----------------------------------------------------------------------===// 234 235 namespace clang { 236 namespace diag { 237 using CustomDiagDesc = DiagnosticIDs::CustomDiagDesc; 238 class CustomDiagInfo { 239 std::vector<CustomDiagDesc> DiagInfo; 240 std::map<CustomDiagDesc, unsigned> DiagIDs; 241 std::map<diag::Group, std::vector<unsigned>> GroupToDiags; 242 243 public: 244 /// getDescription - Return the description of the specified custom 245 /// diagnostic. 246 const CustomDiagDesc &getDescription(unsigned DiagID) const { 247 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 248 "Invalid diagnostic ID"); 249 return DiagInfo[DiagID - DIAG_UPPER_LIMIT]; 250 } 251 252 unsigned getOrCreateDiagID(DiagnosticIDs::CustomDiagDesc D) { 253 // Check to see if it already exists. 254 std::map<CustomDiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 255 if (I != DiagIDs.end() && I->first == D) 256 return I->second; 257 258 // If not, assign a new ID. 259 unsigned ID = DiagInfo.size() + DIAG_UPPER_LIMIT; 260 DiagIDs.insert(std::make_pair(D, ID)); 261 DiagInfo.push_back(D); 262 if (auto Group = D.GetGroup()) 263 GroupToDiags[*Group].emplace_back(ID); 264 return ID; 265 } 266 267 ArrayRef<unsigned> getDiagsInGroup(diag::Group G) const { 268 if (auto Diags = GroupToDiags.find(G); Diags != GroupToDiags.end()) 269 return Diags->second; 270 return {}; 271 } 272 }; 273 274 } // namespace diag 275 } // namespace clang 276 277 DiagnosticMapping DiagnosticIDs::getDefaultMapping(unsigned DiagID) const { 278 DiagnosticMapping Info = DiagnosticMapping::Make( 279 diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); 280 281 if (IsCustomDiag(DiagID)) { 282 Info.setSeverity( 283 CustomDiagInfo->getDescription(DiagID).GetDefaultSeverity()); 284 } else if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { 285 Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity); 286 287 if (StaticInfo->WarnNoWerror) { 288 assert(Info.getSeverity() == diag::Severity::Warning && 289 "Unexpected mapping with no-Werror bit!"); 290 Info.setNoWarningAsError(true); 291 } 292 } 293 294 return Info; 295 } 296 297 void DiagnosticIDs::initCustomDiagMapping(DiagnosticMapping &Mapping, 298 unsigned DiagID) { 299 assert(IsCustomDiag(DiagID)); 300 const auto &Diag = CustomDiagInfo->getDescription(DiagID); 301 if (auto Group = Diag.GetGroup()) { 302 GroupInfo GroupInfo = GroupInfos[static_cast<size_t>(*Group)]; 303 if (static_cast<diag::Severity>(GroupInfo.Severity) != diag::Severity()) 304 Mapping.setSeverity(static_cast<diag::Severity>(GroupInfo.Severity)); 305 Mapping.setNoWarningAsError(GroupInfo.HasNoWarningAsError); 306 } else { 307 Mapping.setSeverity(Diag.GetDefaultSeverity()); 308 Mapping.setNoWarningAsError(true); 309 Mapping.setNoErrorAsFatal(true); 310 } 311 } 312 313 /// getCategoryNumberForDiag - Return the category number that a specified 314 /// DiagID belongs to, or 0 if no category. 315 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 316 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 317 return Info->Category; 318 return 0; 319 } 320 321 namespace { 322 // The diagnostic category names. 323 struct StaticDiagCategoryRec { 324 const char *NameStr; 325 uint8_t NameLen; 326 327 StringRef getName() const { 328 return StringRef(NameStr, NameLen); 329 } 330 }; 331 } 332 333 static const StaticDiagCategoryRec CategoryNameTable[] = { 334 #define GET_CATEGORY_TABLE 335 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 336 #include "clang/Basic/DiagnosticGroups.inc" 337 #undef GET_CATEGORY_TABLE 338 { nullptr, 0 } 339 }; 340 341 /// getNumberOfCategories - Return the number of categories 342 unsigned DiagnosticIDs::getNumberOfCategories() { 343 return std::size(CategoryNameTable) - 1; 344 } 345 346 /// getCategoryNameFromID - Given a category ID, return the name of the 347 /// category, an empty string if CategoryID is zero, or null if CategoryID is 348 /// invalid. 349 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 350 if (CategoryID >= getNumberOfCategories()) 351 return StringRef(); 352 return CategoryNameTable[CategoryID].getName(); 353 } 354 355 356 357 DiagnosticIDs::SFINAEResponse 358 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 359 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 360 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 361 return SFINAE_Report; 362 } 363 364 bool DiagnosticIDs::isDeferrable(unsigned DiagID) { 365 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 366 return Info->Deferrable; 367 return false; 368 } 369 370 //===----------------------------------------------------------------------===// 371 // Common Diagnostic implementation 372 //===----------------------------------------------------------------------===// 373 374 DiagnosticIDs::DiagnosticIDs() {} 375 376 DiagnosticIDs::~DiagnosticIDs() {} 377 378 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 379 /// and level. If this is the first request for this diagnostic, it is 380 /// registered and created, otherwise the existing ID is returned. 381 /// 382 /// \param FormatString A fixed diagnostic format string that will be hashed and 383 /// mapped to a unique DiagID. 384 unsigned DiagnosticIDs::getCustomDiagID(CustomDiagDesc Diag) { 385 if (!CustomDiagInfo) 386 CustomDiagInfo.reset(new diag::CustomDiagInfo()); 387 return CustomDiagInfo->getOrCreateDiagID(Diag); 388 } 389 390 bool DiagnosticIDs::isWarningOrExtension(unsigned DiagID) const { 391 return DiagID < diag::DIAG_UPPER_LIMIT 392 ? getDiagClass(DiagID) != CLASS_ERROR 393 : CustomDiagInfo->getDescription(DiagID).GetClass() != CLASS_ERROR; 394 } 395 396 /// Determine whether the given built-in diagnostic ID is a 397 /// Note. 398 bool DiagnosticIDs::isNote(unsigned DiagID) const { 399 return DiagID < diag::DIAG_UPPER_LIMIT && getDiagClass(DiagID) == CLASS_NOTE; 400 } 401 402 /// isExtensionDiag - Determine whether the given built-in diagnostic 403 /// ID is for an extension of some sort. This also returns EnabledByDefault, 404 /// which is set to indicate whether the diagnostic is ignored by default (in 405 /// which case -pedantic enables it) or treated as a warning/error by default. 406 /// 407 bool DiagnosticIDs::isExtensionDiag(unsigned DiagID, 408 bool &EnabledByDefault) const { 409 if (IsCustomDiag(DiagID) || getDiagClass(DiagID) != CLASS_EXTENSION) 410 return false; 411 412 EnabledByDefault = 413 getDefaultMapping(DiagID).getSeverity() != diag::Severity::Ignored; 414 return true; 415 } 416 417 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) const { 418 return getDefaultMapping(DiagID).getSeverity() >= diag::Severity::Error; 419 } 420 421 /// getDescription - Given a diagnostic ID, return a description of the 422 /// issue. 423 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 424 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 425 return Info->getDescription(); 426 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 427 return CustomDiagInfo->getDescription(DiagID).GetDescription(); 428 } 429 430 static DiagnosticIDs::Level toLevel(diag::Severity SV) { 431 switch (SV) { 432 case diag::Severity::Ignored: 433 return DiagnosticIDs::Ignored; 434 case diag::Severity::Remark: 435 return DiagnosticIDs::Remark; 436 case diag::Severity::Warning: 437 return DiagnosticIDs::Warning; 438 case diag::Severity::Error: 439 return DiagnosticIDs::Error; 440 case diag::Severity::Fatal: 441 return DiagnosticIDs::Fatal; 442 } 443 llvm_unreachable("unexpected severity"); 444 } 445 446 /// getDiagnosticLevel - Based on the way the client configured the 447 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 448 /// by consumable the DiagnosticClient. 449 DiagnosticIDs::Level 450 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 451 const DiagnosticsEngine &Diag) const { 452 unsigned DiagClass = getDiagClass(DiagID); 453 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; 454 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); 455 } 456 457 /// Based on the way the client configured the Diagnostic 458 /// object, classify the specified diagnostic ID into a Level, consumable by 459 /// the DiagnosticClient. 460 /// 461 /// \param Loc The source location we are interested in finding out the 462 /// diagnostic state. Can be null in order to query the latest state. 463 diag::Severity 464 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 465 const DiagnosticsEngine &Diag) const { 466 bool IsCustomDiag = DiagnosticIDs::IsCustomDiag(DiagID); 467 assert(getDiagClass(DiagID) != CLASS_NOTE); 468 469 // Specific non-error diagnostics may be mapped to various levels from ignored 470 // to error. Errors can only be mapped to fatal. 471 diag::Severity Result = diag::Severity::Fatal; 472 473 // Get the mapping information, or compute it lazily. 474 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc); 475 DiagnosticMapping Mapping = State->getOrAddMapping((diag::kind)DiagID); 476 477 // TODO: Can a null severity really get here? 478 if (Mapping.getSeverity() != diag::Severity()) 479 Result = Mapping.getSeverity(); 480 481 // Upgrade ignored diagnostics if -Weverything is enabled. 482 if (State->EnableAllWarnings && Result == diag::Severity::Ignored && 483 !Mapping.isUser() && 484 (IsCustomDiag || getDiagClass(DiagID) != CLASS_REMARK)) 485 Result = diag::Severity::Warning; 486 487 // Ignore -pedantic diagnostics inside __extension__ blocks. 488 // (The diagnostics controlled by -pedantic are the extension diagnostics 489 // that are not enabled by default.) 490 bool EnabledByDefault = false; 491 bool IsExtensionDiag = isExtensionDiag(DiagID, EnabledByDefault); 492 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 493 return diag::Severity::Ignored; 494 495 // For extension diagnostics that haven't been explicitly mapped, check if we 496 // should upgrade the diagnostic. 497 if (IsExtensionDiag && !Mapping.isUser()) 498 Result = std::max(Result, State->ExtBehavior); 499 500 // At this point, ignored errors can no longer be upgraded. 501 if (Result == diag::Severity::Ignored) 502 return Result; 503 504 // Honor -w: this disables all messages which are not Error/Fatal by 505 // default (disregarding attempts to upgrade severity from Warning to Error), 506 // as well as disabling all messages which are currently mapped to Warning 507 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma 508 // diagnostic.) 509 // FIXME: Should -w be ignored for custom warnings without a group? 510 if (State->IgnoreAllWarnings) { 511 if ((!IsCustomDiag || CustomDiagInfo->getDescription(DiagID).GetGroup()) && 512 (Result == diag::Severity::Warning || 513 (Result >= diag::Severity::Error && 514 !isDefaultMappingAsError((diag::kind)DiagID)))) 515 return diag::Severity::Ignored; 516 } 517 518 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 519 if (Result == diag::Severity::Warning) { 520 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 521 Result = diag::Severity::Error; 522 } 523 524 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly 525 // disabled. 526 if (Result == diag::Severity::Error) { 527 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 528 Result = diag::Severity::Fatal; 529 } 530 531 // If explicitly requested, map fatal errors to errors. 532 if (Result == diag::Severity::Fatal && 533 DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) 534 Result = diag::Severity::Error; 535 536 // Rest of the mappings are only applicable for diagnostics associated with a 537 // SourceLocation, bail out early for others. 538 if (!Diag.hasSourceManager()) 539 return Result; 540 541 const auto &SM = Diag.getSourceManager(); 542 543 bool ShowInSystemHeader = 544 IsCustomDiag 545 ? CustomDiagInfo->getDescription(DiagID).ShouldShowInSystemHeader() 546 : !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 547 548 // If we are in a system header, we ignore it. We look at the diagnostic class 549 // because we also want to ignore extensions and warnings in -Werror and 550 // -pedantic-errors modes, which *map* warnings/extensions to errors. 551 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 552 SM.isInSystemHeader(SM.getExpansionLoc(Loc))) 553 return diag::Severity::Ignored; 554 555 // We also ignore warnings due to system macros 556 bool ShowInSystemMacro = 557 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro; 558 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() && 559 SM.isInSystemMacro(Loc)) 560 return diag::Severity::Ignored; 561 562 // Clang-diagnostics pragmas always take precedence over suppression mapping. 563 if (!Mapping.isPragma() && Diag.isSuppressedViaMapping(DiagID, Loc)) 564 return diag::Severity::Ignored; 565 566 return Result; 567 } 568 569 DiagnosticIDs::Class DiagnosticIDs::getDiagClass(unsigned DiagID) const { 570 if (IsCustomDiag(DiagID)) 571 return Class(CustomDiagInfo->getDescription(DiagID).GetClass()); 572 573 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 574 return Class(Info->Class); 575 return CLASS_INVALID; 576 } 577 578 #define GET_DIAG_ARRAYS 579 #include "clang/Basic/DiagnosticGroups.inc" 580 #undef GET_DIAG_ARRAYS 581 582 namespace { 583 struct WarningOption { 584 uint16_t NameOffset; 585 uint16_t Members; 586 uint16_t SubGroups; 587 StringRef Documentation; 588 589 StringRef getName() const { return DiagGroupNames[NameOffset]; } 590 }; 591 } 592 593 // Second the table of options, sorted by name for fast binary lookup. 594 static const WarningOption OptionTable[] = { 595 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ 596 {FlagNameOffset, Members, SubGroups, Docs}, 597 #include "clang/Basic/DiagnosticGroups.inc" 598 #undef DIAG_ENTRY 599 }; 600 601 /// Given a diagnostic group ID, return its documentation. 602 StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) { 603 return OptionTable[static_cast<int>(Group)].Documentation; 604 } 605 606 StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { 607 return OptionTable[static_cast<int>(Group)].getName(); 608 } 609 610 std::optional<diag::Group> 611 DiagnosticIDs::getGroupForWarningOption(StringRef Name) { 612 const auto *Found = llvm::partition_point( 613 OptionTable, [=](const WarningOption &O) { return O.getName() < Name; }); 614 if (Found == std::end(OptionTable) || Found->getName() != Name) 615 return std::nullopt; 616 return static_cast<diag::Group>(Found - OptionTable); 617 } 618 619 std::optional<diag::Group> 620 DiagnosticIDs::getGroupForDiag(unsigned DiagID) const { 621 if (IsCustomDiag(DiagID)) { 622 assert(CustomDiagInfo); 623 return CustomDiagInfo->getDescription(DiagID).GetGroup(); 624 } 625 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 626 return static_cast<diag::Group>(Info->getOptionGroupIndex()); 627 return std::nullopt; 628 } 629 630 /// getWarningOptionForDiag - Return the lowest-level warning option that 631 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 632 /// the diagnostic, this returns null. 633 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 634 if (auto G = getGroupForDiag(DiagID)) 635 return getWarningOptionForGroup(*G); 636 return StringRef(); 637 } 638 639 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 640 std::vector<std::string> Res{"-W", "-Wno-"}; 641 for (StringRef Name : DiagGroupNames) { 642 if (Name.empty()) 643 continue; 644 645 Res.push_back((Twine("-W") + Name).str()); 646 Res.push_back((Twine("-Wno-") + Name).str()); 647 } 648 649 return Res; 650 } 651 652 /// Return \c true if any diagnostics were found in this group, even if they 653 /// were filtered out due to having the wrong flavor. 654 static bool getDiagnosticsInGroup(diag::Flavor Flavor, 655 const WarningOption *Group, 656 SmallVectorImpl<diag::kind> &Diags, 657 diag::CustomDiagInfo *CustomDiagInfo) { 658 // An empty group is considered to be a warning group: we have empty groups 659 // for GCC compatibility, and GCC does not have remarks. 660 if (!Group->Members && !Group->SubGroups) 661 return Flavor == diag::Flavor::Remark; 662 663 bool NotFound = true; 664 665 // Add the members of the option diagnostic set. 666 const int16_t *Member = DiagArrays + Group->Members; 667 for (; *Member != -1; ++Member) { 668 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 669 NotFound = false; 670 Diags.push_back(*Member); 671 } 672 } 673 674 // Add the members of the subgroups. 675 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 676 for (; *SubGroups != (int16_t)-1; ++SubGroups) { 677 if (CustomDiagInfo) 678 llvm::copy( 679 CustomDiagInfo->getDiagsInGroup(static_cast<diag::Group>(*SubGroups)), 680 std::back_inserter(Diags)); 681 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 682 Diags, CustomDiagInfo); 683 } 684 685 return NotFound; 686 } 687 688 bool 689 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 690 SmallVectorImpl<diag::kind> &Diags) const { 691 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) { 692 if (CustomDiagInfo) 693 llvm::copy(CustomDiagInfo->getDiagsInGroup(*G), 694 std::back_inserter(Diags)); 695 return ::getDiagnosticsInGroup(Flavor, 696 &OptionTable[static_cast<unsigned>(*G)], 697 Diags, CustomDiagInfo.get()); 698 } 699 return true; 700 } 701 702 template <class Func> 703 static void forEachSubGroupImpl(const WarningOption *Group, Func func) { 704 for (const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 705 *SubGroups != -1; ++SubGroups) { 706 func(static_cast<size_t>(*SubGroups)); 707 forEachSubGroupImpl(&OptionTable[*SubGroups], std::move(func)); 708 } 709 } 710 711 template <class Func> 712 static void forEachSubGroup(diag::Group Group, Func func) { 713 const WarningOption *WarningOpt = &OptionTable[static_cast<size_t>(Group)]; 714 func(static_cast<size_t>(Group)); 715 ::forEachSubGroupImpl(WarningOpt, std::move(func)); 716 } 717 718 void DiagnosticIDs::setGroupSeverity(StringRef Group, diag::Severity Sev) { 719 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) { 720 ::forEachSubGroup(*G, [&](size_t SubGroup) { 721 GroupInfos[SubGroup].Severity = static_cast<unsigned>(Sev); 722 }); 723 } 724 } 725 726 void DiagnosticIDs::setGroupNoWarningsAsError(StringRef Group, bool Val) { 727 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) { 728 ::forEachSubGroup(*G, [&](size_t SubGroup) { 729 GroupInfos[static_cast<size_t>(*G)].HasNoWarningAsError = Val; 730 }); 731 } 732 } 733 734 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 735 std::vector<diag::kind> &Diags) { 736 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 737 if (StaticDiagInfo[i].getFlavor() == Flavor) 738 Diags.push_back(StaticDiagInfo[i].DiagID); 739 } 740 741 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 742 StringRef Group) { 743 StringRef Best; 744 unsigned BestDistance = Group.size() + 1; // Maximum threshold. 745 for (const WarningOption &O : OptionTable) { 746 // Don't suggest ignored warning flags. 747 if (!O.Members && !O.SubGroups) 748 continue; 749 750 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 751 if (Distance > BestDistance) 752 continue; 753 754 // Don't suggest groups that are not of this kind. 755 llvm::SmallVector<diag::kind, 8> Diags; 756 if (::getDiagnosticsInGroup(Flavor, &O, Diags, nullptr) || Diags.empty()) 757 continue; 758 759 if (Distance == BestDistance) { 760 // Two matches with the same distance, don't prefer one over the other. 761 Best = ""; 762 } else if (Distance < BestDistance) { 763 // This is a better match. 764 Best = O.getName(); 765 BestDistance = Distance; 766 } 767 } 768 769 return Best; 770 } 771 772 /// ProcessDiag - This is the method used to report a diagnostic that is 773 /// finally fully formed. 774 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag, 775 const DiagnosticBuilder &DiagBuilder) const { 776 Diagnostic Info(&Diag, DiagBuilder); 777 778 assert(Diag.getClient() && "DiagnosticClient not set!"); 779 780 // Figure out the diagnostic level of this message. 781 unsigned DiagID = Info.getID(); 782 DiagnosticIDs::Level DiagLevel 783 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 784 785 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 786 // or diagnostics are suppressed. 787 if (DiagLevel >= DiagnosticIDs::Error) { 788 ++Diag.TrapNumErrorsOccurred; 789 if (isUnrecoverable(DiagID)) 790 ++Diag.TrapNumUnrecoverableErrorsOccurred; 791 } 792 793 if (Diag.SuppressAllDiagnostics) 794 return false; 795 796 if (DiagLevel != DiagnosticIDs::Note) { 797 // Record that a fatal error occurred only when we see a second 798 // non-note diagnostic. This allows notes to be attached to the 799 // fatal error, but suppresses any diagnostics that follow those 800 // notes. 801 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 802 Diag.FatalErrorOccurred = true; 803 804 Diag.LastDiagLevel = DiagLevel; 805 } 806 807 // If a fatal error has already been emitted, silence all subsequent 808 // diagnostics. 809 if (Diag.FatalErrorOccurred) { 810 if (DiagLevel >= DiagnosticIDs::Error && 811 Diag.Client->IncludeInDiagnosticCounts()) { 812 ++Diag.NumErrors; 813 } 814 815 return false; 816 } 817 818 // If the client doesn't care about this message, don't issue it. If this is 819 // a note and the last real diagnostic was ignored, ignore it too. 820 if (DiagLevel == DiagnosticIDs::Ignored || 821 (DiagLevel == DiagnosticIDs::Note && 822 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 823 return false; 824 825 if (DiagLevel >= DiagnosticIDs::Error) { 826 if (isUnrecoverable(DiagID)) 827 Diag.UnrecoverableErrorOccurred = true; 828 829 // Warnings which have been upgraded to errors do not prevent compilation. 830 if (isDefaultMappingAsError(DiagID)) 831 Diag.UncompilableErrorOccurred = true; 832 833 Diag.ErrorOccurred = true; 834 if (Diag.Client->IncludeInDiagnosticCounts()) { 835 ++Diag.NumErrors; 836 } 837 838 // If we've emitted a lot of errors, emit a fatal error instead of it to 839 // stop a flood of bogus errors. 840 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 841 DiagLevel == DiagnosticIDs::Error) { 842 Diag.Report(diag::fatal_too_many_errors); 843 return false; 844 } 845 } 846 847 // Make sure we set FatalErrorOccurred to ensure that the notes from the 848 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 849 if (Info.getID() == diag::fatal_too_many_errors) 850 Diag.FatalErrorOccurred = true; 851 // Finally, report it. 852 EmitDiag(Diag, DiagBuilder, DiagLevel); 853 return true; 854 } 855 856 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, 857 const DiagnosticBuilder &DiagBuilder, 858 Level DiagLevel) const { 859 Diagnostic Info(&Diag, DiagBuilder); 860 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 861 862 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 863 if (Diag.Client->IncludeInDiagnosticCounts()) { 864 if (DiagLevel == DiagnosticIDs::Warning) 865 ++Diag.NumWarnings; 866 } 867 } 868 869 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 870 // Only errors may be unrecoverable. 871 if (getDiagClass(DiagID) < CLASS_ERROR) 872 return false; 873 874 if (DiagID == diag::err_unavailable || 875 DiagID == diag::err_unavailable_message) 876 return false; 877 878 // Currently we consider all ARC errors as recoverable. 879 if (isARCDiagnostic(DiagID)) 880 return false; 881 882 if (isCodegenABICheckDiagnostic(DiagID)) 883 return false; 884 885 return true; 886 } 887 888 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 889 unsigned cat = getCategoryNumberForDiag(DiagID); 890 return DiagnosticIDs::getCategoryNameFromID(cat).starts_with("ARC "); 891 } 892 893 bool DiagnosticIDs::isCodegenABICheckDiagnostic(unsigned DiagID) { 894 unsigned cat = getCategoryNumberForDiag(DiagID); 895 return DiagnosticIDs::getCategoryNameFromID(cat) == "Codegen ABI Check"; 896 } 897