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 : 6; 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 VALIDATE_DIAG_SIZE(REFACTORING) 92 #undef VALIDATE_DIAG_SIZE 93 #undef STRINGIFY_NAME 94 95 } // namespace anonymous 96 97 static 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 120 static 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. 124 static 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 } 145 CATEGORY(DRIVER, COMMON) 146 CATEGORY(FRONTEND, DRIVER) 147 CATEGORY(SERIALIZATION, FRONTEND) 148 CATEGORY(LEX, SERIALIZATION) 149 CATEGORY(PARSE, LEX) 150 CATEGORY(AST, PARSE) 151 CATEGORY(COMMENT, AST) 152 CATEGORY(CROSSTU, COMMENT) 153 CATEGORY(SEMA, CROSSTU) 154 CATEGORY(ANALYSIS, SEMA) 155 CATEGORY(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 173 static 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. 192 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 193 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 194 return Info->Category; 195 return 0; 196 } 197 198 namespace { 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. 213 DiagnosticMapping & 214 DiagnosticsEngine::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 225 static 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 234 unsigned 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. 241 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 242 if (CategoryID >= getNumberOfCategories()) 243 return StringRef(); 244 return CategoryNameTable[CategoryID].getName(); 245 } 246 247 248 249 DiagnosticIDs::SFINAEResponse 250 DiagnosticIDs::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 /// 258 static 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 268 namespace 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, 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 315 DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; } 316 317 DiagnosticIDs::~DiagnosticIDs() { 318 delete CustomDiagInfo; 319 } 320 321 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 322 /// and level. If this is the first request for this diagnostic, it is 323 /// registered and created, otherwise the existing ID is returned. 324 /// 325 /// \param FormatString A fixed diagnostic format string that will be hashed and 326 /// mapped to a unique DiagID. 327 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { 328 if (!CustomDiagInfo) 329 CustomDiagInfo = new diag::CustomDiagInfo(); 330 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); 331 } 332 333 334 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 335 /// level of the specified diagnostic ID is a Warning or Extension. 336 /// This only works on builtin diagnostics, not custom ones, and is not legal to 337 /// call on NOTEs. 338 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 339 return DiagID < diag::DIAG_UPPER_LIMIT && 340 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 341 } 342 343 /// Determine whether the given built-in diagnostic ID is a 344 /// Note. 345 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { 346 return DiagID < diag::DIAG_UPPER_LIMIT && 347 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 348 } 349 350 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 351 /// ID is for an extension of some sort. This also returns EnabledByDefault, 352 /// which is set to indicate whether the diagnostic is ignored by default (in 353 /// which case -pedantic enables it) or treated as a warning/error by default. 354 /// 355 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, 356 bool &EnabledByDefault) { 357 if (DiagID >= diag::DIAG_UPPER_LIMIT || 358 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) 359 return false; 360 361 EnabledByDefault = 362 GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored; 363 return true; 364 } 365 366 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { 367 if (DiagID >= diag::DIAG_UPPER_LIMIT) 368 return false; 369 370 return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error; 371 } 372 373 /// getDescription - Given a diagnostic ID, return a description of the 374 /// issue. 375 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 376 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 377 return Info->getDescription(); 378 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 379 return CustomDiagInfo->getDescription(DiagID); 380 } 381 382 static DiagnosticIDs::Level toLevel(diag::Severity SV) { 383 switch (SV) { 384 case diag::Severity::Ignored: 385 return DiagnosticIDs::Ignored; 386 case diag::Severity::Remark: 387 return DiagnosticIDs::Remark; 388 case diag::Severity::Warning: 389 return DiagnosticIDs::Warning; 390 case diag::Severity::Error: 391 return DiagnosticIDs::Error; 392 case diag::Severity::Fatal: 393 return DiagnosticIDs::Fatal; 394 } 395 llvm_unreachable("unexpected severity"); 396 } 397 398 /// getDiagnosticLevel - Based on the way the client configured the 399 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 400 /// by consumable the DiagnosticClient. 401 DiagnosticIDs::Level 402 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 403 const DiagnosticsEngine &Diag) const { 404 // Handle custom diagnostics, which cannot be mapped. 405 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 406 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 407 return CustomDiagInfo->getLevel(DiagID); 408 } 409 410 unsigned DiagClass = getBuiltinDiagClass(DiagID); 411 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; 412 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); 413 } 414 415 /// Based on the way the client configured the Diagnostic 416 /// object, classify the specified diagnostic ID into a Level, consumable by 417 /// the DiagnosticClient. 418 /// 419 /// \param Loc The source location we are interested in finding out the 420 /// diagnostic state. Can be null in order to query the latest state. 421 diag::Severity 422 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 423 const DiagnosticsEngine &Diag) const { 424 assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); 425 426 // Specific non-error diagnostics may be mapped to various levels from ignored 427 // to error. Errors can only be mapped to fatal. 428 diag::Severity Result = diag::Severity::Fatal; 429 430 // Get the mapping information, or compute it lazily. 431 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc); 432 DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); 433 434 // TODO: Can a null severity really get here? 435 if (Mapping.getSeverity() != diag::Severity()) 436 Result = Mapping.getSeverity(); 437 438 // Upgrade ignored diagnostics if -Weverything is enabled. 439 if (State->EnableAllWarnings && Result == diag::Severity::Ignored && 440 !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) 441 Result = diag::Severity::Warning; 442 443 // Ignore -pedantic diagnostics inside __extension__ blocks. 444 // (The diagnostics controlled by -pedantic are the extension diagnostics 445 // that are not enabled by default.) 446 bool EnabledByDefault = false; 447 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); 448 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 449 return diag::Severity::Ignored; 450 451 // For extension diagnostics that haven't been explicitly mapped, check if we 452 // should upgrade the diagnostic. 453 if (IsExtensionDiag && !Mapping.isUser()) 454 Result = std::max(Result, State->ExtBehavior); 455 456 // At this point, ignored errors can no longer be upgraded. 457 if (Result == diag::Severity::Ignored) 458 return Result; 459 460 // Honor -w, which is lower in priority than pedantic-errors, but higher than 461 // -Werror. 462 // FIXME: Under GCC, this also suppresses warnings that have been mapped to 463 // errors by -W flags and #pragma diagnostic. 464 if (Result == diag::Severity::Warning && State->IgnoreAllWarnings) 465 return diag::Severity::Ignored; 466 467 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 468 if (Result == diag::Severity::Warning) { 469 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 470 Result = diag::Severity::Error; 471 } 472 473 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly 474 // disabled. 475 if (Result == diag::Severity::Error) { 476 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 477 Result = diag::Severity::Fatal; 478 } 479 480 // Custom diagnostics always are emitted in system headers. 481 bool ShowInSystemHeader = 482 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 483 484 // If we are in a system header, we ignore it. We look at the diagnostic class 485 // because we also want to ignore extensions and warnings in -Werror and 486 // -pedantic-errors modes, which *map* warnings/extensions to errors. 487 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 488 Diag.getSourceManager().isInSystemHeader( 489 Diag.getSourceManager().getExpansionLoc(Loc))) 490 return diag::Severity::Ignored; 491 492 return Result; 493 } 494 495 #define GET_DIAG_ARRAYS 496 #include "clang/Basic/DiagnosticGroups.inc" 497 #undef GET_DIAG_ARRAYS 498 499 namespace { 500 struct WarningOption { 501 uint16_t NameOffset; 502 uint16_t Members; 503 uint16_t SubGroups; 504 505 // String is stored with a pascal-style length byte. 506 StringRef getName() const { 507 return StringRef(DiagGroupNames + NameOffset + 1, 508 DiagGroupNames[NameOffset]); 509 } 510 }; 511 } 512 513 // Second the table of options, sorted by name for fast binary lookup. 514 static const WarningOption OptionTable[] = { 515 #define GET_DIAG_TABLE 516 #include "clang/Basic/DiagnosticGroups.inc" 517 #undef GET_DIAG_TABLE 518 }; 519 520 /// getWarningOptionForDiag - Return the lowest-level warning option that 521 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 522 /// the diagnostic, this returns null. 523 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 524 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 525 return OptionTable[Info->getOptionGroupIndex()].getName(); 526 return StringRef(); 527 } 528 529 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 530 std::vector<std::string> Res; 531 for (size_t I = 1; DiagGroupNames[I] != '\0';) { 532 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); 533 I += DiagGroupNames[I] + 1; 534 Res.push_back("-W" + Diag); 535 Res.push_back("-Wno-" + Diag); 536 } 537 538 return Res; 539 } 540 541 /// Return \c true if any diagnostics were found in this group, even if they 542 /// were filtered out due to having the wrong flavor. 543 static bool getDiagnosticsInGroup(diag::Flavor Flavor, 544 const WarningOption *Group, 545 SmallVectorImpl<diag::kind> &Diags) { 546 // An empty group is considered to be a warning group: we have empty groups 547 // for GCC compatibility, and GCC does not have remarks. 548 if (!Group->Members && !Group->SubGroups) 549 return Flavor == diag::Flavor::Remark; 550 551 bool NotFound = true; 552 553 // Add the members of the option diagnostic set. 554 const int16_t *Member = DiagArrays + Group->Members; 555 for (; *Member != -1; ++Member) { 556 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 557 NotFound = false; 558 Diags.push_back(*Member); 559 } 560 } 561 562 // Add the members of the subgroups. 563 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 564 for (; *SubGroups != (int16_t)-1; ++SubGroups) 565 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 566 Diags); 567 568 return NotFound; 569 } 570 571 bool 572 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 573 SmallVectorImpl<diag::kind> &Diags) const { 574 auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable), 575 Group, 576 [](const WarningOption &LHS, StringRef RHS) { 577 return LHS.getName() < RHS; 578 }); 579 if (Found == std::end(OptionTable) || Found->getName() != Group) 580 return true; // Option not found. 581 582 return ::getDiagnosticsInGroup(Flavor, Found, Diags); 583 } 584 585 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 586 std::vector<diag::kind> &Diags) { 587 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 588 if (StaticDiagInfo[i].getFlavor() == Flavor) 589 Diags.push_back(StaticDiagInfo[i].DiagID); 590 } 591 592 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 593 StringRef Group) { 594 StringRef Best; 595 unsigned BestDistance = Group.size() + 1; // Sanity threshold. 596 for (const WarningOption &O : OptionTable) { 597 // Don't suggest ignored warning flags. 598 if (!O.Members && !O.SubGroups) 599 continue; 600 601 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 602 if (Distance > BestDistance) 603 continue; 604 605 // Don't suggest groups that are not of this kind. 606 llvm::SmallVector<diag::kind, 8> Diags; 607 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty()) 608 continue; 609 610 if (Distance == BestDistance) { 611 // Two matches with the same distance, don't prefer one over the other. 612 Best = ""; 613 } else if (Distance < BestDistance) { 614 // This is a better match. 615 Best = O.getName(); 616 BestDistance = Distance; 617 } 618 } 619 620 return Best; 621 } 622 623 /// ProcessDiag - This is the method used to report a diagnostic that is 624 /// finally fully formed. 625 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 626 Diagnostic Info(&Diag); 627 628 assert(Diag.getClient() && "DiagnosticClient not set!"); 629 630 // Figure out the diagnostic level of this message. 631 unsigned DiagID = Info.getID(); 632 DiagnosticIDs::Level DiagLevel 633 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 634 635 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 636 // or diagnostics are suppressed. 637 if (DiagLevel >= DiagnosticIDs::Error) { 638 ++Diag.TrapNumErrorsOccurred; 639 if (isUnrecoverable(DiagID)) 640 ++Diag.TrapNumUnrecoverableErrorsOccurred; 641 } 642 643 if (Diag.SuppressAllDiagnostics) 644 return false; 645 646 if (DiagLevel != DiagnosticIDs::Note) { 647 // Record that a fatal error occurred only when we see a second 648 // non-note diagnostic. This allows notes to be attached to the 649 // fatal error, but suppresses any diagnostics that follow those 650 // notes. 651 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 652 Diag.FatalErrorOccurred = true; 653 654 Diag.LastDiagLevel = DiagLevel; 655 } 656 657 // If a fatal error has already been emitted, silence all subsequent 658 // diagnostics. 659 if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) { 660 if (DiagLevel >= DiagnosticIDs::Error && 661 Diag.Client->IncludeInDiagnosticCounts()) { 662 ++Diag.NumErrors; 663 } 664 665 return false; 666 } 667 668 // If the client doesn't care about this message, don't issue it. If this is 669 // a note and the last real diagnostic was ignored, ignore it too. 670 if (DiagLevel == DiagnosticIDs::Ignored || 671 (DiagLevel == DiagnosticIDs::Note && 672 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 673 return false; 674 675 if (DiagLevel >= DiagnosticIDs::Error) { 676 if (isUnrecoverable(DiagID)) 677 Diag.UnrecoverableErrorOccurred = true; 678 679 // Warnings which have been upgraded to errors do not prevent compilation. 680 if (isDefaultMappingAsError(DiagID)) 681 Diag.UncompilableErrorOccurred = true; 682 683 Diag.ErrorOccurred = true; 684 if (Diag.Client->IncludeInDiagnosticCounts()) { 685 ++Diag.NumErrors; 686 } 687 688 // If we've emitted a lot of errors, emit a fatal error instead of it to 689 // stop a flood of bogus errors. 690 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 691 DiagLevel == DiagnosticIDs::Error) { 692 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 693 return false; 694 } 695 } 696 697 // Make sure we set FatalErrorOccurred to ensure that the notes from the 698 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 699 if (Diag.CurDiagID == diag::fatal_too_many_errors) 700 Diag.FatalErrorOccurred = true; 701 // Finally, report it. 702 EmitDiag(Diag, DiagLevel); 703 return true; 704 } 705 706 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { 707 Diagnostic Info(&Diag); 708 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 709 710 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 711 if (Diag.Client->IncludeInDiagnosticCounts()) { 712 if (DiagLevel == DiagnosticIDs::Warning) 713 ++Diag.NumWarnings; 714 } 715 716 Diag.CurDiagID = ~0U; 717 } 718 719 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 720 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 721 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 722 // Custom diagnostics. 723 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 724 } 725 726 // Only errors may be unrecoverable. 727 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 728 return false; 729 730 if (DiagID == diag::err_unavailable || 731 DiagID == diag::err_unavailable_message) 732 return false; 733 734 // Currently we consider all ARC errors as recoverable. 735 if (isARCDiagnostic(DiagID)) 736 return false; 737 738 return true; 739 } 740 741 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 742 unsigned cat = getCategoryNumberForDiag(DiagID); 743 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 744 } 745