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