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