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