1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the Diagnostic IDs-related interfaces. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Basic/DiagnosticIDs.h" 15 #include "clang/Basic/AllDiagnostics.h" 16 #include "clang/Basic/DiagnosticCategories.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include <map> 22 using namespace clang; 23 24 //===----------------------------------------------------------------------===// 25 // Builtin Diagnostic information 26 //===----------------------------------------------------------------------===// 27 28 namespace { 29 30 // Diagnostic classes. 31 enum { 32 CLASS_NOTE = 0x01, 33 CLASS_REMARK = 0x02, 34 CLASS_WARNING = 0x03, 35 CLASS_EXTENSION = 0x04, 36 CLASS_ERROR = 0x05 37 }; 38 39 struct StaticDiagInfoRec { 40 uint16_t DiagID; 41 unsigned DefaultSeverity : 3; 42 unsigned Class : 3; 43 unsigned SFINAE : 2; 44 unsigned WarnNoWerror : 1; 45 unsigned WarnShowInSystemHeader : 1; 46 unsigned Category : 5; 47 48 uint16_t OptionGroupIndex; 49 50 uint16_t DescriptionLen; 51 const char *DescriptionStr; 52 53 unsigned getOptionGroupIndex() const { 54 return OptionGroupIndex; 55 } 56 57 StringRef getDescription() const { 58 return StringRef(DescriptionStr, DescriptionLen); 59 } 60 61 diag::Flavor getFlavor() const { 62 return Class == CLASS_REMARK ? diag::Flavor::Remark 63 : diag::Flavor::WarningOrError; 64 } 65 66 bool operator<(const StaticDiagInfoRec &RHS) const { 67 return DiagID < RHS.DiagID; 68 } 69 }; 70 71 #define STRINGIFY_NAME(NAME) #NAME 72 #define VALIDATE_DIAG_SIZE(NAME) \ 73 static_assert( \ 74 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ 75 static_cast<unsigned>(diag::DIAG_START_##NAME) + \ 76 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \ 77 STRINGIFY_NAME( \ 78 DIAG_SIZE_##NAME) " is insufficient to contain all " \ 79 "diagnostics, it may need to be made larger in " \ 80 "DiagnosticIDs.h."); 81 VALIDATE_DIAG_SIZE(COMMON) 82 VALIDATE_DIAG_SIZE(DRIVER) 83 VALIDATE_DIAG_SIZE(FRONTEND) 84 VALIDATE_DIAG_SIZE(SERIALIZATION) 85 VALIDATE_DIAG_SIZE(LEX) 86 VALIDATE_DIAG_SIZE(PARSE) 87 VALIDATE_DIAG_SIZE(AST) 88 VALIDATE_DIAG_SIZE(COMMENT) 89 VALIDATE_DIAG_SIZE(SEMA) 90 VALIDATE_DIAG_SIZE(ANALYSIS) 91 #undef VALIDATE_DIAG_SIZE 92 #undef STRINGIFY_NAME 93 94 } // namespace anonymous 95 96 static 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 #undef DIAG 116 }; 117 118 static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo); 119 120 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 121 /// or null if the ID is invalid. 122 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 123 // Out of bounds diag. Can't be in the table. 124 using namespace diag; 125 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) 126 return nullptr; 127 128 // Compute the index of the requested diagnostic in the static table. 129 // 1. Add the number of diagnostics in each category preceding the 130 // diagnostic and of the category the diagnostic is in. This gives us 131 // the offset of the category in the table. 132 // 2. Subtract the number of IDs in each category from our ID. This gives us 133 // the offset of the diagnostic in the category. 134 // This is cheaper than a binary search on the table as it doesn't touch 135 // memory at all. 136 unsigned Offset = 0; 137 unsigned ID = DiagID - DIAG_START_COMMON - 1; 138 #define CATEGORY(NAME, PREV) \ 139 if (DiagID > DIAG_START_##NAME) { \ 140 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ 141 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ 142 } 143 CATEGORY(DRIVER, COMMON) 144 CATEGORY(FRONTEND, DRIVER) 145 CATEGORY(SERIALIZATION, FRONTEND) 146 CATEGORY(LEX, SERIALIZATION) 147 CATEGORY(PARSE, LEX) 148 CATEGORY(AST, PARSE) 149 CATEGORY(COMMENT, AST) 150 CATEGORY(CROSSTU, COMMENT) 151 CATEGORY(SEMA, CROSSTU) 152 CATEGORY(ANALYSIS, SEMA) 153 #undef CATEGORY 154 155 // Avoid out of bounds reads. 156 if (ID + Offset >= StaticDiagInfoSize) 157 return nullptr; 158 159 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); 160 161 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset]; 162 // If the diag id doesn't match we found a different diag, abort. This can 163 // happen when this function is called with an ID that points into a hole in 164 // the diagID space. 165 if (Found->DiagID != DiagID) 166 return nullptr; 167 return Found; 168 } 169 170 static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) { 171 DiagnosticMapping Info = DiagnosticMapping::Make( 172 diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); 173 174 if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { 175 Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity); 176 177 if (StaticInfo->WarnNoWerror) { 178 assert(Info.getSeverity() == diag::Severity::Warning && 179 "Unexpected mapping with no-Werror bit!"); 180 Info.setNoWarningAsError(true); 181 } 182 } 183 184 return Info; 185 } 186 187 /// getCategoryNumberForDiag - Return the category number that a specified 188 /// DiagID belongs to, or 0 if no category. 189 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 190 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 191 return Info->Category; 192 return 0; 193 } 194 195 namespace { 196 // The diagnostic category names. 197 struct StaticDiagCategoryRec { 198 const char *NameStr; 199 uint8_t NameLen; 200 201 StringRef getName() const { 202 return StringRef(NameStr, NameLen); 203 } 204 }; 205 } 206 207 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not 208 // particularly clean, but for now we just implement this method here so we can 209 // access GetDefaultDiagMapping. 210 DiagnosticMapping & 211 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { 212 std::pair<iterator, bool> Result = 213 DiagMap.insert(std::make_pair(Diag, DiagnosticMapping())); 214 215 // Initialize the entry if we added it. 216 if (Result.second) 217 Result.first->second = GetDefaultDiagMapping(Diag); 218 219 return Result.first->second; 220 } 221 222 static const StaticDiagCategoryRec CategoryNameTable[] = { 223 #define GET_CATEGORY_TABLE 224 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 225 #include "clang/Basic/DiagnosticGroups.inc" 226 #undef GET_CATEGORY_TABLE 227 { nullptr, 0 } 228 }; 229 230 /// getNumberOfCategories - Return the number of categories 231 unsigned DiagnosticIDs::getNumberOfCategories() { 232 return llvm::array_lengthof(CategoryNameTable) - 1; 233 } 234 235 /// getCategoryNameFromID - Given a category ID, return the name of the 236 /// category, an empty string if CategoryID is zero, or null if CategoryID is 237 /// invalid. 238 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 239 if (CategoryID >= getNumberOfCategories()) 240 return StringRef(); 241 return CategoryNameTable[CategoryID].getName(); 242 } 243 244 245 246 DiagnosticIDs::SFINAEResponse 247 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 248 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 249 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 250 return SFINAE_Report; 251 } 252 253 /// getBuiltinDiagClass - Return the class field of the diagnostic. 254 /// 255 static unsigned getBuiltinDiagClass(unsigned DiagID) { 256 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 257 return Info->Class; 258 return ~0U; 259 } 260 261 //===----------------------------------------------------------------------===// 262 // Custom Diagnostic information 263 //===----------------------------------------------------------------------===// 264 265 namespace clang { 266 namespace diag { 267 class CustomDiagInfo { 268 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc; 269 std::vector<DiagDesc> DiagInfo; 270 std::map<DiagDesc, unsigned> DiagIDs; 271 public: 272 273 /// getDescription - Return the description of the specified custom 274 /// diagnostic. 275 StringRef getDescription(unsigned DiagID) const { 276 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 277 "Invalid diagnostic ID"); 278 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; 279 } 280 281 /// getLevel - Return the level of the specified custom diagnostic. 282 DiagnosticIDs::Level getLevel(unsigned DiagID) const { 283 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 284 "Invalid diagnostic ID"); 285 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 286 } 287 288 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, 289 DiagnosticIDs &Diags) { 290 DiagDesc D(L, Message); 291 // Check to see if it already exists. 292 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 293 if (I != DiagIDs.end() && I->first == D) 294 return I->second; 295 296 // If not, assign a new ID. 297 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 298 DiagIDs.insert(std::make_pair(D, ID)); 299 DiagInfo.push_back(D); 300 return ID; 301 } 302 }; 303 304 } // end diag namespace 305 } // end clang namespace 306 307 308 //===----------------------------------------------------------------------===// 309 // Common Diagnostic implementation 310 //===----------------------------------------------------------------------===// 311 312 DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; } 313 314 DiagnosticIDs::~DiagnosticIDs() { 315 delete CustomDiagInfo; 316 } 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. 324 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { 325 if (!CustomDiagInfo) 326 CustomDiagInfo = 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. 335 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 336 return DiagID < diag::DIAG_UPPER_LIMIT && 337 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 338 } 339 340 /// \brief Determine whether the given built-in diagnostic ID is a 341 /// Note. 342 bool 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 /// 352 bool 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 363 bool 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. 372 StringRef 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 379 static 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. 398 DiagnosticIDs::Level 399 DiagnosticIDs::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 /// \brief 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. 418 diag::Severity 419 DiagnosticIDs::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, which is lower in priority than pedantic-errors, but higher than 458 // -Werror. 459 // FIXME: Under GCC, this also suppresses warnings that have been mapped to 460 // errors by -W flags and #pragma diagnostic. 461 if (Result == diag::Severity::Warning && State->IgnoreAllWarnings) 462 return diag::Severity::Ignored; 463 464 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 465 if (Result == diag::Severity::Warning) { 466 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 467 Result = diag::Severity::Error; 468 } 469 470 // If -Wfatal-errors is enabled, map errors to fatal unless explicity 471 // disabled. 472 if (Result == diag::Severity::Error) { 473 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 474 Result = diag::Severity::Fatal; 475 } 476 477 // Custom diagnostics always are emitted in system headers. 478 bool ShowInSystemHeader = 479 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 480 481 // If we are in a system header, we ignore it. We look at the diagnostic class 482 // because we also want to ignore extensions and warnings in -Werror and 483 // -pedantic-errors modes, which *map* warnings/extensions to errors. 484 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 485 Diag.getSourceManager().isInSystemHeader( 486 Diag.getSourceManager().getExpansionLoc(Loc))) 487 return diag::Severity::Ignored; 488 489 return Result; 490 } 491 492 #define GET_DIAG_ARRAYS 493 #include "clang/Basic/DiagnosticGroups.inc" 494 #undef GET_DIAG_ARRAYS 495 496 namespace { 497 struct WarningOption { 498 uint16_t NameOffset; 499 uint16_t Members; 500 uint16_t SubGroups; 501 502 // String is stored with a pascal-style length byte. 503 StringRef getName() const { 504 return StringRef(DiagGroupNames + NameOffset + 1, 505 DiagGroupNames[NameOffset]); 506 } 507 }; 508 } 509 510 // Second the table of options, sorted by name for fast binary lookup. 511 static const WarningOption OptionTable[] = { 512 #define GET_DIAG_TABLE 513 #include "clang/Basic/DiagnosticGroups.inc" 514 #undef GET_DIAG_TABLE 515 }; 516 517 /// getWarningOptionForDiag - Return the lowest-level warning option that 518 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 519 /// the diagnostic, this returns null. 520 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 521 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 522 return OptionTable[Info->getOptionGroupIndex()].getName(); 523 return StringRef(); 524 } 525 526 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 527 std::vector<std::string> Res; 528 for (size_t I = 1; DiagGroupNames[I] != '\0';) { 529 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); 530 I += DiagGroupNames[I] + 1; 531 Res.push_back("-W" + Diag); 532 Res.push_back("-Wno-" + Diag); 533 } 534 535 return Res; 536 } 537 538 /// Return \c true if any diagnostics were found in this group, even if they 539 /// were filtered out due to having the wrong flavor. 540 static bool getDiagnosticsInGroup(diag::Flavor Flavor, 541 const WarningOption *Group, 542 SmallVectorImpl<diag::kind> &Diags) { 543 // An empty group is considered to be a warning group: we have empty groups 544 // for GCC compatibility, and GCC does not have remarks. 545 if (!Group->Members && !Group->SubGroups) 546 return Flavor == diag::Flavor::Remark; 547 548 bool NotFound = true; 549 550 // Add the members of the option diagnostic set. 551 const int16_t *Member = DiagArrays + Group->Members; 552 for (; *Member != -1; ++Member) { 553 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 554 NotFound = false; 555 Diags.push_back(*Member); 556 } 557 } 558 559 // Add the members of the subgroups. 560 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 561 for (; *SubGroups != (int16_t)-1; ++SubGroups) 562 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 563 Diags); 564 565 return NotFound; 566 } 567 568 bool 569 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 570 SmallVectorImpl<diag::kind> &Diags) const { 571 auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable), 572 Group, 573 [](const WarningOption &LHS, StringRef RHS) { 574 return LHS.getName() < RHS; 575 }); 576 if (Found == std::end(OptionTable) || Found->getName() != Group) 577 return true; // Option not found. 578 579 return ::getDiagnosticsInGroup(Flavor, Found, Diags); 580 } 581 582 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 583 SmallVectorImpl<diag::kind> &Diags) const { 584 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 585 if (StaticDiagInfo[i].getFlavor() == Flavor) 586 Diags.push_back(StaticDiagInfo[i].DiagID); 587 } 588 589 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 590 StringRef Group) { 591 StringRef Best; 592 unsigned BestDistance = Group.size() + 1; // Sanity threshold. 593 for (const WarningOption &O : OptionTable) { 594 // Don't suggest ignored warning flags. 595 if (!O.Members && !O.SubGroups) 596 continue; 597 598 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 599 if (Distance > BestDistance) 600 continue; 601 602 // Don't suggest groups that are not of this kind. 603 llvm::SmallVector<diag::kind, 8> Diags; 604 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty()) 605 continue; 606 607 if (Distance == BestDistance) { 608 // Two matches with the same distance, don't prefer one over the other. 609 Best = ""; 610 } else if (Distance < BestDistance) { 611 // This is a better match. 612 Best = O.getName(); 613 BestDistance = Distance; 614 } 615 } 616 617 return Best; 618 } 619 620 /// ProcessDiag - This is the method used to report a diagnostic that is 621 /// finally fully formed. 622 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 623 Diagnostic Info(&Diag); 624 625 assert(Diag.getClient() && "DiagnosticClient not set!"); 626 627 // Figure out the diagnostic level of this message. 628 unsigned DiagID = Info.getID(); 629 DiagnosticIDs::Level DiagLevel 630 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 631 632 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 633 // or diagnostics are suppressed. 634 if (DiagLevel >= DiagnosticIDs::Error) { 635 ++Diag.TrapNumErrorsOccurred; 636 if (isUnrecoverable(DiagID)) 637 ++Diag.TrapNumUnrecoverableErrorsOccurred; 638 } 639 640 if (Diag.SuppressAllDiagnostics) 641 return false; 642 643 if (DiagLevel != DiagnosticIDs::Note) { 644 // Record that a fatal error occurred only when we see a second 645 // non-note diagnostic. This allows notes to be attached to the 646 // fatal error, but suppresses any diagnostics that follow those 647 // notes. 648 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 649 Diag.FatalErrorOccurred = true; 650 651 Diag.LastDiagLevel = DiagLevel; 652 } 653 654 // If a fatal error has already been emitted, silence all subsequent 655 // diagnostics. 656 if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) { 657 if (DiagLevel >= DiagnosticIDs::Error && 658 Diag.Client->IncludeInDiagnosticCounts()) { 659 ++Diag.NumErrors; 660 } 661 662 return false; 663 } 664 665 // If the client doesn't care about this message, don't issue it. If this is 666 // a note and the last real diagnostic was ignored, ignore it too. 667 if (DiagLevel == DiagnosticIDs::Ignored || 668 (DiagLevel == DiagnosticIDs::Note && 669 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 670 return false; 671 672 if (DiagLevel >= DiagnosticIDs::Error) { 673 if (isUnrecoverable(DiagID)) 674 Diag.UnrecoverableErrorOccurred = true; 675 676 // Warnings which have been upgraded to errors do not prevent compilation. 677 if (isDefaultMappingAsError(DiagID)) 678 Diag.UncompilableErrorOccurred = true; 679 680 Diag.ErrorOccurred = true; 681 if (Diag.Client->IncludeInDiagnosticCounts()) { 682 ++Diag.NumErrors; 683 } 684 685 // If we've emitted a lot of errors, emit a fatal error instead of it to 686 // stop a flood of bogus errors. 687 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 688 DiagLevel == DiagnosticIDs::Error) { 689 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 690 return false; 691 } 692 } 693 694 // Make sure we set FatalErrorOccurred to ensure that the notes from the 695 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 696 if (Diag.CurDiagID == diag::fatal_too_many_errors) 697 Diag.FatalErrorOccurred = true; 698 // Finally, report it. 699 EmitDiag(Diag, DiagLevel); 700 return true; 701 } 702 703 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { 704 Diagnostic Info(&Diag); 705 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 706 707 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 708 if (Diag.Client->IncludeInDiagnosticCounts()) { 709 if (DiagLevel == DiagnosticIDs::Warning) 710 ++Diag.NumWarnings; 711 } 712 713 Diag.CurDiagID = ~0U; 714 } 715 716 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 717 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 718 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 719 // Custom diagnostics. 720 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 721 } 722 723 // Only errors may be unrecoverable. 724 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 725 return false; 726 727 if (DiagID == diag::err_unavailable || 728 DiagID == diag::err_unavailable_message) 729 return false; 730 731 // Currently we consider all ARC errors as recoverable. 732 if (isARCDiagnostic(DiagID)) 733 return false; 734 735 return true; 736 } 737 738 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 739 unsigned cat = getCategoryNumberForDiag(DiagID); 740 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 741 } 742