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