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 259static DiagnosticMapping GetDefaultDiagMapping(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 296// Unfortunately, the split between DiagnosticIDs and Diagnostic is not 297// particularly clean, but for now we just implement this method here so we can 298// access GetDefaultDiagMapping. 299DiagnosticMapping & 300DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { 301 std::pair<iterator, bool> Result = 302 DiagMap.insert(std::make_pair(Diag, DiagnosticMapping())); 303 304 // Initialize the entry if we added it. 305 if (Result.second) 306 Result.first->second = GetDefaultDiagMapping(Diag); 307 308 return Result.first->second; 309} 310 311static const StaticDiagCategoryRec CategoryNameTable[] = { 312#define GET_CATEGORY_TABLE 313#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 314#include "clang/Basic/DiagnosticGroups.inc" 315#undef GET_CATEGORY_TABLE 316 { nullptr, 0 } 317}; 318 319/// getNumberOfCategories - Return the number of categories 320unsigned DiagnosticIDs::getNumberOfCategories() { 321 return std::size(CategoryNameTable) - 1; 322} 323 324/// getCategoryNameFromID - Given a category ID, return the name of the 325/// category, an empty string if CategoryID is zero, or null if CategoryID is 326/// invalid. 327StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 328 if (CategoryID >= getNumberOfCategories()) 329 return StringRef(); 330 return CategoryNameTable[CategoryID].getName(); 331} 332 333 334 335DiagnosticIDs::SFINAEResponse 336DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 337 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 338 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 339 return SFINAE_Report; 340} 341 342bool DiagnosticIDs::isDeferrable(unsigned DiagID) { 343 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 344 return Info->Deferrable; 345 return false; 346} 347 348/// getBuiltinDiagClass - Return the class field of the diagnostic. 349/// 350static unsigned getBuiltinDiagClass(unsigned DiagID) { 351 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 352 return Info->Class; 353 return ~0U; 354} 355 356//===----------------------------------------------------------------------===// 357// Custom Diagnostic information 358//===----------------------------------------------------------------------===// 359 360namespace clang { 361 namespace diag { 362 class CustomDiagInfo { 363 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc; 364 std::vector<DiagDesc> DiagInfo; 365 std::map<DiagDesc, unsigned> DiagIDs; 366 public: 367 368 /// getDescription - Return the description of the specified custom 369 /// diagnostic. 370 StringRef getDescription(unsigned DiagID) const { 371 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 372 "Invalid diagnostic ID"); 373 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; 374 } 375 376 /// getLevel - Return the level of the specified custom diagnostic. 377 DiagnosticIDs::Level getLevel(unsigned DiagID) const { 378 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 379 "Invalid diagnostic ID"); 380 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 381 } 382 383 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, 384 DiagnosticIDs &Diags) { 385 DiagDesc D(L, std::string(Message)); 386 // Check to see if it already exists. 387 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 388 if (I != DiagIDs.end() && I->first == D) 389 return I->second; 390 391 // If not, assign a new ID. 392 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 393 DiagIDs.insert(std::make_pair(D, ID)); 394 DiagInfo.push_back(D); 395 return ID; 396 } 397 }; 398 399 } // end diag namespace 400} // end clang namespace 401 402 403//===----------------------------------------------------------------------===// 404// Common Diagnostic implementation 405//===----------------------------------------------------------------------===// 406 407DiagnosticIDs::DiagnosticIDs() {} 408 409DiagnosticIDs::~DiagnosticIDs() {} 410 411/// getCustomDiagID - Return an ID for a diagnostic with the specified message 412/// and level. If this is the first request for this diagnostic, it is 413/// registered and created, otherwise the existing ID is returned. 414/// 415/// \param FormatString A fixed diagnostic format string that will be hashed and 416/// mapped to a unique DiagID. 417unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { 418 if (!CustomDiagInfo) 419 CustomDiagInfo.reset(new diag::CustomDiagInfo()); 420 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); 421} 422 423 424/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 425/// level of the specified diagnostic ID is a Warning or Extension. 426/// This only works on builtin diagnostics, not custom ones, and is not legal to 427/// call on NOTEs. 428bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 429 return DiagID < diag::DIAG_UPPER_LIMIT && 430 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 431} 432 433/// Determine whether the given built-in diagnostic ID is a 434/// Note. 435bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { 436 return DiagID < diag::DIAG_UPPER_LIMIT && 437 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 438} 439 440/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 441/// ID is for an extension of some sort. This also returns EnabledByDefault, 442/// which is set to indicate whether the diagnostic is ignored by default (in 443/// which case -pedantic enables it) or treated as a warning/error by default. 444/// 445bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, 446 bool &EnabledByDefault) { 447 if (DiagID >= diag::DIAG_UPPER_LIMIT || 448 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) 449 return false; 450 451 EnabledByDefault = 452 GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored; 453 return true; 454} 455 456bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { 457 if (DiagID >= diag::DIAG_UPPER_LIMIT) 458 return false; 459 460 return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error; 461} 462 463/// getDescription - Given a diagnostic ID, return a description of the 464/// issue. 465StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 466 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 467 return Info->getDescription(); 468 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 469 return CustomDiagInfo->getDescription(DiagID); 470} 471 472static DiagnosticIDs::Level toLevel(diag::Severity SV) { 473 switch (SV) { 474 case diag::Severity::Ignored: 475 return DiagnosticIDs::Ignored; 476 case diag::Severity::Remark: 477 return DiagnosticIDs::Remark; 478 case diag::Severity::Warning: 479 return DiagnosticIDs::Warning; 480 case diag::Severity::Error: 481 return DiagnosticIDs::Error; 482 case diag::Severity::Fatal: 483 return DiagnosticIDs::Fatal; 484 } 485 llvm_unreachable("unexpected severity"); 486} 487 488/// getDiagnosticLevel - Based on the way the client configured the 489/// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 490/// by consumable the DiagnosticClient. 491DiagnosticIDs::Level 492DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 493 const DiagnosticsEngine &Diag) const { 494 // Handle custom diagnostics, which cannot be mapped. 495 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 496 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 497 return CustomDiagInfo->getLevel(DiagID); 498 } 499 500 unsigned DiagClass = getBuiltinDiagClass(DiagID); 501 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; 502 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); 503} 504 505/// Based on the way the client configured the Diagnostic 506/// object, classify the specified diagnostic ID into a Level, consumable by 507/// the DiagnosticClient. 508/// 509/// \param Loc The source location we are interested in finding out the 510/// diagnostic state. Can be null in order to query the latest state. 511diag::Severity 512DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 513 const DiagnosticsEngine &Diag) const { 514 assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); 515 516 // Specific non-error diagnostics may be mapped to various levels from ignored 517 // to error. Errors can only be mapped to fatal. 518 diag::Severity Result = diag::Severity::Fatal; 519 520 // Get the mapping information, or compute it lazily. 521 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc); 522 DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); 523 524 // TODO: Can a null severity really get here? 525 if (Mapping.getSeverity() != diag::Severity()) 526 Result = Mapping.getSeverity(); 527 528 // Upgrade ignored diagnostics if -Weverything is enabled. 529 if (State->EnableAllWarnings && Result == diag::Severity::Ignored && 530 !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) 531 Result = diag::Severity::Warning; 532 533 // Ignore -pedantic diagnostics inside __extension__ blocks. 534 // (The diagnostics controlled by -pedantic are the extension diagnostics 535 // that are not enabled by default.) 536 bool EnabledByDefault = false; 537 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); 538 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 539 return diag::Severity::Ignored; 540 541 // For extension diagnostics that haven't been explicitly mapped, check if we 542 // should upgrade the diagnostic. 543 if (IsExtensionDiag && !Mapping.isUser()) 544 Result = std::max(Result, State->ExtBehavior); 545 546 // At this point, ignored errors can no longer be upgraded. 547 if (Result == diag::Severity::Ignored) 548 return Result; 549 550 // Honor -w: this disables all messages which are not Error/Fatal by 551 // default (disregarding attempts to upgrade severity from Warning to Error), 552 // as well as disabling all messages which are currently mapped to Warning 553 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma 554 // diagnostic.) 555 if (State->IgnoreAllWarnings) { 556 if (Result == diag::Severity::Warning || 557 (Result >= diag::Severity::Error && 558 !isDefaultMappingAsError((diag::kind)DiagID))) 559 return diag::Severity::Ignored; 560 } 561 562 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 563 if (Result == diag::Severity::Warning) { 564 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 565 Result = diag::Severity::Error; 566 } 567 568 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly 569 // disabled. 570 if (Result == diag::Severity::Error) { 571 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 572 Result = diag::Severity::Fatal; 573 } 574 575 // If explicitly requested, map fatal errors to errors. 576 if (Result == diag::Severity::Fatal && 577 Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) 578 Result = diag::Severity::Error; 579 580 // Custom diagnostics always are emitted in system headers. 581 bool ShowInSystemHeader = 582 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 583 584 // If we are in a system header, we ignore it. We look at the diagnostic class 585 // because we also want to ignore extensions and warnings in -Werror and 586 // -pedantic-errors modes, which *map* warnings/extensions to errors. 587 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 588 Diag.getSourceManager().isInSystemHeader( 589 Diag.getSourceManager().getExpansionLoc(Loc))) 590 return diag::Severity::Ignored; 591 592 // We also ignore warnings due to system macros 593 bool ShowInSystemMacro = 594 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro; 595 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() && 596 Diag.getSourceManager().isInSystemMacro(Loc)) 597 return diag::Severity::Ignored; 598 599 return Result; 600} 601 602#define GET_DIAG_ARRAYS 603#include "clang/Basic/DiagnosticGroups.inc" 604#undef GET_DIAG_ARRAYS 605 606namespace { 607 struct WarningOption { 608 uint16_t NameOffset; 609 uint16_t Members; 610 uint16_t SubGroups; 611 StringRef Documentation; 612 613 // String is stored with a pascal-style length byte. 614 StringRef getName() const { 615 return StringRef(DiagGroupNames + NameOffset + 1, 616 DiagGroupNames[NameOffset]); 617 } 618 }; 619} 620 621// Second the table of options, sorted by name for fast binary lookup. 622static const WarningOption OptionTable[] = { 623#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ 624 {FlagNameOffset, Members, SubGroups, Docs}, 625#include "clang/Basic/DiagnosticGroups.inc" 626#undef DIAG_ENTRY 627}; 628 629/// Given a diagnostic group ID, return its documentation. 630StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) { 631 return OptionTable[static_cast<int>(Group)].Documentation; 632} 633 634StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { 635 return OptionTable[static_cast<int>(Group)].getName(); 636} 637 638std::optional<diag::Group> 639DiagnosticIDs::getGroupForWarningOption(StringRef Name) { 640 const auto *Found = llvm::partition_point( 641 OptionTable, [=](const WarningOption &O) { return O.getName() < Name; }); 642 if (Found == std::end(OptionTable) || Found->getName() != Name) 643 return std::nullopt; 644 return static_cast<diag::Group>(Found - OptionTable); 645} 646 647std::optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) { 648 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 649 return static_cast<diag::Group>(Info->getOptionGroupIndex()); 650 return std::nullopt; 651} 652 653/// getWarningOptionForDiag - Return the lowest-level warning option that 654/// enables the specified diagnostic. If there is no -Wfoo flag that controls 655/// the diagnostic, this returns null. 656StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 657 if (auto G = getGroupForDiag(DiagID)) 658 return getWarningOptionForGroup(*G); 659 return StringRef(); 660} 661 662std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 663 std::vector<std::string> Res{"-W", "-Wno-"}; 664 for (size_t I = 1; DiagGroupNames[I] != '\0';) { 665 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); 666 I += DiagGroupNames[I] + 1; 667 Res.push_back("-W" + Diag); 668 Res.push_back("-Wno-" + Diag); 669 } 670 671 return Res; 672} 673 674/// Return \c true if any diagnostics were found in this group, even if they 675/// were filtered out due to having the wrong flavor. 676static bool getDiagnosticsInGroup(diag::Flavor Flavor, 677 const WarningOption *Group, 678 SmallVectorImpl<diag::kind> &Diags) { 679 // An empty group is considered to be a warning group: we have empty groups 680 // for GCC compatibility, and GCC does not have remarks. 681 if (!Group->Members && !Group->SubGroups) 682 return Flavor == diag::Flavor::Remark; 683 684 bool NotFound = true; 685 686 // Add the members of the option diagnostic set. 687 const int16_t *Member = DiagArrays + Group->Members; 688 for (; *Member != -1; ++Member) { 689 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 690 NotFound = false; 691 Diags.push_back(*Member); 692 } 693 } 694 695 // Add the members of the subgroups. 696 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 697 for (; *SubGroups != (int16_t)-1; ++SubGroups) 698 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 699 Diags); 700 701 return NotFound; 702} 703 704bool 705DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 706 SmallVectorImpl<diag::kind> &Diags) const { 707 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) 708 return ::getDiagnosticsInGroup( 709 Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags); 710 return true; 711} 712 713void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 714 std::vector<diag::kind> &Diags) { 715 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 716 if (StaticDiagInfo[i].getFlavor() == Flavor) 717 Diags.push_back(StaticDiagInfo[i].DiagID); 718} 719 720StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 721 StringRef Group) { 722 StringRef Best; 723 unsigned BestDistance = Group.size() + 1; // Maximum threshold. 724 for (const WarningOption &O : OptionTable) { 725 // Don't suggest ignored warning flags. 726 if (!O.Members && !O.SubGroups) 727 continue; 728 729 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 730 if (Distance > BestDistance) 731 continue; 732 733 // Don't suggest groups that are not of this kind. 734 llvm::SmallVector<diag::kind, 8> Diags; 735 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty()) 736 continue; 737 738 if (Distance == BestDistance) { 739 // Two matches with the same distance, don't prefer one over the other. 740 Best = ""; 741 } else if (Distance < BestDistance) { 742 // This is a better match. 743 Best = O.getName(); 744 BestDistance = Distance; 745 } 746 } 747 748 return Best; 749} 750 751/// ProcessDiag - This is the method used to report a diagnostic that is 752/// finally fully formed. 753bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 754 Diagnostic Info(&Diag); 755 756 assert(Diag.getClient() && "DiagnosticClient not set!"); 757 758 // Figure out the diagnostic level of this message. 759 unsigned DiagID = Info.getID(); 760 DiagnosticIDs::Level DiagLevel 761 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 762 763 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 764 // or diagnostics are suppressed. 765 if (DiagLevel >= DiagnosticIDs::Error) { 766 ++Diag.TrapNumErrorsOccurred; 767 if (isUnrecoverable(DiagID)) 768 ++Diag.TrapNumUnrecoverableErrorsOccurred; 769 } 770 771 if (Diag.SuppressAllDiagnostics) 772 return false; 773 774 if (DiagLevel != DiagnosticIDs::Note) { 775 // Record that a fatal error occurred only when we see a second 776 // non-note diagnostic. This allows notes to be attached to the 777 // fatal error, but suppresses any diagnostics that follow those 778 // notes. 779 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 780 Diag.FatalErrorOccurred = true; 781 782 Diag.LastDiagLevel = DiagLevel; 783 } 784 785 // If a fatal error has already been emitted, silence all subsequent 786 // diagnostics. 787 if (Diag.FatalErrorOccurred) { 788 if (DiagLevel >= DiagnosticIDs::Error && 789 Diag.Client->IncludeInDiagnosticCounts()) { 790 ++Diag.NumErrors; 791 } 792 793 return false; 794 } 795 796 // If the client doesn't care about this message, don't issue it. If this is 797 // a note and the last real diagnostic was ignored, ignore it too. 798 if (DiagLevel == DiagnosticIDs::Ignored || 799 (DiagLevel == DiagnosticIDs::Note && 800 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 801 return false; 802 803 if (DiagLevel >= DiagnosticIDs::Error) { 804 if (isUnrecoverable(DiagID)) 805 Diag.UnrecoverableErrorOccurred = true; 806 807 // Warnings which have been upgraded to errors do not prevent compilation. 808 if (isDefaultMappingAsError(DiagID)) 809 Diag.UncompilableErrorOccurred = true; 810 811 Diag.ErrorOccurred = true; 812 if (Diag.Client->IncludeInDiagnosticCounts()) { 813 ++Diag.NumErrors; 814 } 815 816 // If we've emitted a lot of errors, emit a fatal error instead of it to 817 // stop a flood of bogus errors. 818 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 819 DiagLevel == DiagnosticIDs::Error) { 820 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 821 return false; 822 } 823 } 824 825 // Make sure we set FatalErrorOccurred to ensure that the notes from the 826 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 827 if (Diag.CurDiagID == diag::fatal_too_many_errors) 828 Diag.FatalErrorOccurred = true; 829 // Finally, report it. 830 EmitDiag(Diag, DiagLevel); 831 return true; 832} 833 834void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { 835 Diagnostic Info(&Diag); 836 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 837 838 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 839 if (Diag.Client->IncludeInDiagnosticCounts()) { 840 if (DiagLevel == DiagnosticIDs::Warning) 841 ++Diag.NumWarnings; 842 } 843 844 Diag.CurDiagID = ~0U; 845} 846 847bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 848 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 849 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 850 // Custom diagnostics. 851 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 852 } 853 854 // Only errors may be unrecoverable. 855 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 856 return false; 857 858 if (DiagID == diag::err_unavailable || 859 DiagID == diag::err_unavailable_message) 860 return false; 861 862 // Currently we consider all ARC errors as recoverable. 863 if (isARCDiagnostic(DiagID)) 864 return false; 865 866 return true; 867} 868 869bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 870 unsigned cat = getCategoryNumberForDiag(DiagID); 871 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 872} 873