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