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/SmallVector.h" 19 #include "llvm/Support/ErrorHandling.h" 20 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_WARNING = 0x02, 34 CLASS_EXTENSION = 0x03, 35 CLASS_ERROR = 0x04 36 }; 37 38 struct StaticDiagInfoRec { 39 unsigned short DiagID; 40 unsigned Mapping : 3; 41 unsigned Class : 3; 42 unsigned SFINAE : 1; 43 unsigned AccessControl : 1; 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 bool operator<(const StaticDiagInfoRec &RHS) const { 62 return DiagID < RHS.DiagID; 63 } 64 }; 65 66 } // namespace anonymous 67 68 static const StaticDiagInfoRec StaticDiagInfo[] = { 69 #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \ 70 SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER, \ 71 CATEGORY) \ 72 { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, \ 73 NOWERROR, SHOWINSYSHEADER, CATEGORY, GROUP, \ 74 STR_SIZE(DESC, uint16_t), DESC }, 75 #include "clang/Basic/DiagnosticCommonKinds.inc" 76 #include "clang/Basic/DiagnosticDriverKinds.inc" 77 #include "clang/Basic/DiagnosticFrontendKinds.inc" 78 #include "clang/Basic/DiagnosticSerializationKinds.inc" 79 #include "clang/Basic/DiagnosticLexKinds.inc" 80 #include "clang/Basic/DiagnosticParseKinds.inc" 81 #include "clang/Basic/DiagnosticASTKinds.inc" 82 #include "clang/Basic/DiagnosticSemaKinds.inc" 83 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 84 #undef DIAG 85 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 86 }; 87 88 static const unsigned StaticDiagInfoSize = 89 sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1; 90 91 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 92 /// or null if the ID is invalid. 93 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 94 // If assertions are enabled, verify that the StaticDiagInfo array is sorted. 95 #ifndef NDEBUG 96 static bool IsFirst = true; 97 if (IsFirst) { 98 for (unsigned i = 1; i != StaticDiagInfoSize; ++i) { 99 assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID && 100 "Diag ID conflict, the enums at the start of clang::diag (in " 101 "DiagnosticIDs.h) probably need to be increased"); 102 103 assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] && 104 "Improperly sorted diag info"); 105 } 106 IsFirst = false; 107 } 108 #endif 109 110 // Search the diagnostic table with a binary search. 111 StaticDiagInfoRec Find = { static_cast<unsigned short>(DiagID), 112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 113 114 const StaticDiagInfoRec *Found = 115 std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find); 116 if (Found == StaticDiagInfo + StaticDiagInfoSize || 117 Found->DiagID != DiagID) 118 return 0; 119 120 return Found; 121 } 122 123 static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) { 124 DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make( 125 diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false); 126 127 if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { 128 Info.setMapping((diag::Mapping) StaticInfo->Mapping); 129 130 if (StaticInfo->WarnNoWerror) { 131 assert(Info.getMapping() == diag::MAP_WARNING && 132 "Unexpected mapping with no-Werror bit!"); 133 Info.setNoWarningAsError(true); 134 } 135 136 if (StaticInfo->WarnShowInSystemHeader) { 137 assert(Info.getMapping() == diag::MAP_WARNING && 138 "Unexpected mapping with show-in-system-header bit!"); 139 Info.setShowInSystemHeader(true); 140 } 141 } 142 143 return Info; 144 } 145 146 /// getCategoryNumberForDiag - Return the category number that a specified 147 /// DiagID belongs to, or 0 if no category. 148 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 149 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 150 return Info->Category; 151 return 0; 152 } 153 154 namespace { 155 // The diagnostic category names. 156 struct StaticDiagCategoryRec { 157 const char *NameStr; 158 uint8_t NameLen; 159 160 StringRef getName() const { 161 return StringRef(NameStr, NameLen); 162 } 163 }; 164 } 165 166 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not 167 // particularly clean, but for now we just implement this method here so we can 168 // access GetDefaultDiagMapping. 169 DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo( 170 diag::kind Diag) 171 { 172 std::pair<iterator, bool> Result = DiagMap.insert( 173 std::make_pair(Diag, DiagnosticMappingInfo())); 174 175 // Initialize the entry if we added it. 176 if (Result.second) 177 Result.first->second = GetDefaultDiagMappingInfo(Diag); 178 179 return Result.first->second; 180 } 181 182 static const StaticDiagCategoryRec CategoryNameTable[] = { 183 #define GET_CATEGORY_TABLE 184 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 185 #include "clang/Basic/DiagnosticGroups.inc" 186 #undef GET_CATEGORY_TABLE 187 { 0, 0 } 188 }; 189 190 /// getNumberOfCategories - Return the number of categories 191 unsigned DiagnosticIDs::getNumberOfCategories() { 192 return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1; 193 } 194 195 /// getCategoryNameFromID - Given a category ID, return the name of the 196 /// category, an empty string if CategoryID is zero, or null if CategoryID is 197 /// invalid. 198 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 199 if (CategoryID >= getNumberOfCategories()) 200 return StringRef(); 201 return CategoryNameTable[CategoryID].getName(); 202 } 203 204 205 206 DiagnosticIDs::SFINAEResponse 207 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 208 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) { 209 if (Info->AccessControl) 210 return SFINAE_AccessControl; 211 212 if (!Info->SFINAE) 213 return SFINAE_Report; 214 215 if (Info->Class == CLASS_ERROR) 216 return SFINAE_SubstitutionFailure; 217 218 // Suppress notes, warnings, and extensions; 219 return SFINAE_Suppress; 220 } 221 222 return SFINAE_Report; 223 } 224 225 /// getBuiltinDiagClass - Return the class field of the diagnostic. 226 /// 227 static unsigned getBuiltinDiagClass(unsigned DiagID) { 228 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 229 return Info->Class; 230 return ~0U; 231 } 232 233 //===----------------------------------------------------------------------===// 234 // Custom Diagnostic information 235 //===----------------------------------------------------------------------===// 236 237 namespace clang { 238 namespace diag { 239 class CustomDiagInfo { 240 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc; 241 std::vector<DiagDesc> DiagInfo; 242 std::map<DiagDesc, unsigned> DiagIDs; 243 public: 244 245 /// getDescription - Return the description of the specified custom 246 /// diagnostic. 247 StringRef getDescription(unsigned DiagID) const { 248 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 249 "Invalid diagnosic ID"); 250 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; 251 } 252 253 /// getLevel - Return the level of the specified custom diagnostic. 254 DiagnosticIDs::Level getLevel(unsigned DiagID) const { 255 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 256 "Invalid diagnosic ID"); 257 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 258 } 259 260 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, 261 DiagnosticIDs &Diags) { 262 DiagDesc D(L, Message); 263 // Check to see if it already exists. 264 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 265 if (I != DiagIDs.end() && I->first == D) 266 return I->second; 267 268 // If not, assign a new ID. 269 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 270 DiagIDs.insert(std::make_pair(D, ID)); 271 DiagInfo.push_back(D); 272 return ID; 273 } 274 }; 275 276 } // end diag namespace 277 } // end clang namespace 278 279 280 //===----------------------------------------------------------------------===// 281 // Common Diagnostic implementation 282 //===----------------------------------------------------------------------===// 283 284 DiagnosticIDs::DiagnosticIDs() { 285 CustomDiagInfo = 0; 286 } 287 288 DiagnosticIDs::~DiagnosticIDs() { 289 delete CustomDiagInfo; 290 } 291 292 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 293 /// and level. If this is the first request for this diagnosic, it is 294 /// registered and created, otherwise the existing ID is returned. 295 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) { 296 if (CustomDiagInfo == 0) 297 CustomDiagInfo = new diag::CustomDiagInfo(); 298 return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); 299 } 300 301 302 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 303 /// level of the specified diagnostic ID is a Warning or Extension. 304 /// This only works on builtin diagnostics, not custom ones, and is not legal to 305 /// call on NOTEs. 306 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 307 return DiagID < diag::DIAG_UPPER_LIMIT && 308 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 309 } 310 311 /// \brief Determine whether the given built-in diagnostic ID is a 312 /// Note. 313 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { 314 return DiagID < diag::DIAG_UPPER_LIMIT && 315 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 316 } 317 318 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 319 /// ID is for an extension of some sort. This also returns EnabledByDefault, 320 /// which is set to indicate whether the diagnostic is ignored by default (in 321 /// which case -pedantic enables it) or treated as a warning/error by default. 322 /// 323 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, 324 bool &EnabledByDefault) { 325 if (DiagID >= diag::DIAG_UPPER_LIMIT || 326 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) 327 return false; 328 329 EnabledByDefault = 330 GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE; 331 return true; 332 } 333 334 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { 335 if (DiagID >= diag::DIAG_UPPER_LIMIT) 336 return false; 337 338 return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR; 339 } 340 341 /// getDescription - Given a diagnostic ID, return a description of the 342 /// issue. 343 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 344 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 345 return Info->getDescription(); 346 return CustomDiagInfo->getDescription(DiagID); 347 } 348 349 /// getDiagnosticLevel - Based on the way the client configured the 350 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 351 /// by consumable the DiagnosticClient. 352 DiagnosticIDs::Level 353 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 354 const DiagnosticsEngine &Diag) const { 355 // Handle custom diagnostics, which cannot be mapped. 356 if (DiagID >= diag::DIAG_UPPER_LIMIT) 357 return CustomDiagInfo->getLevel(DiagID); 358 359 unsigned DiagClass = getBuiltinDiagClass(DiagID); 360 assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); 361 return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag); 362 } 363 364 /// \brief Based on the way the client configured the Diagnostic 365 /// object, classify the specified diagnostic ID into a Level, consumable by 366 /// the DiagnosticClient. 367 /// 368 /// \param Loc The source location we are interested in finding out the 369 /// diagnostic state. Can be null in order to query the latest state. 370 DiagnosticIDs::Level 371 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, 372 SourceLocation Loc, 373 const DiagnosticsEngine &Diag) const { 374 // Specific non-error diagnostics may be mapped to various levels from ignored 375 // to error. Errors can only be mapped to fatal. 376 DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; 377 378 DiagnosticsEngine::DiagStatePointsTy::iterator 379 Pos = Diag.GetDiagStatePointForLoc(Loc); 380 DiagnosticsEngine::DiagState *State = Pos->State; 381 382 // Get the mapping information, or compute it lazily. 383 DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( 384 (diag::kind)DiagID); 385 386 switch (MappingInfo.getMapping()) { 387 case diag::MAP_IGNORE: 388 Result = DiagnosticIDs::Ignored; 389 break; 390 case diag::MAP_WARNING: 391 Result = DiagnosticIDs::Warning; 392 break; 393 case diag::MAP_ERROR: 394 Result = DiagnosticIDs::Error; 395 break; 396 case diag::MAP_FATAL: 397 Result = DiagnosticIDs::Fatal; 398 break; 399 } 400 401 // Upgrade ignored diagnostics if -Weverything is enabled. 402 if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored && 403 !MappingInfo.isUser()) 404 Result = DiagnosticIDs::Warning; 405 406 // Ignore -pedantic diagnostics inside __extension__ blocks. 407 // (The diagnostics controlled by -pedantic are the extension diagnostics 408 // that are not enabled by default.) 409 bool EnabledByDefault = false; 410 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); 411 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 412 return DiagnosticIDs::Ignored; 413 414 // For extension diagnostics that haven't been explicitly mapped, check if we 415 // should upgrade the diagnostic. 416 if (IsExtensionDiag && !MappingInfo.isUser()) { 417 switch (Diag.ExtBehavior) { 418 case DiagnosticsEngine::Ext_Ignore: 419 break; 420 case DiagnosticsEngine::Ext_Warn: 421 // Upgrade ignored diagnostics to warnings. 422 if (Result == DiagnosticIDs::Ignored) 423 Result = DiagnosticIDs::Warning; 424 break; 425 case DiagnosticsEngine::Ext_Error: 426 // Upgrade ignored or warning diagnostics to errors. 427 if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning) 428 Result = DiagnosticIDs::Error; 429 break; 430 } 431 } 432 433 // At this point, ignored errors can no longer be upgraded. 434 if (Result == DiagnosticIDs::Ignored) 435 return Result; 436 437 // Honor -w, which is lower in priority than pedantic-errors, but higher than 438 // -Werror. 439 if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings) 440 return DiagnosticIDs::Ignored; 441 442 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 443 if (Result == DiagnosticIDs::Warning) { 444 if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError()) 445 Result = DiagnosticIDs::Error; 446 } 447 448 // If -Wfatal-errors is enabled, map errors to fatal unless explicity 449 // disabled. 450 if (Result == DiagnosticIDs::Error) { 451 if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal()) 452 Result = DiagnosticIDs::Fatal; 453 } 454 455 // If we are in a system header, we ignore it. We look at the diagnostic class 456 // because we also want to ignore extensions and warnings in -Werror and 457 // -pedantic-errors modes, which *map* warnings/extensions to errors. 458 if (Result >= DiagnosticIDs::Warning && 459 DiagClass != CLASS_ERROR && 460 // Custom diagnostics always are emitted in system headers. 461 DiagID < diag::DIAG_UPPER_LIMIT && 462 !MappingInfo.hasShowInSystemHeader() && 463 Diag.SuppressSystemWarnings && 464 Loc.isValid() && 465 Diag.getSourceManager().isInSystemHeader( 466 Diag.getSourceManager().getExpansionLoc(Loc))) 467 return DiagnosticIDs::Ignored; 468 469 return Result; 470 } 471 472 struct clang::WarningOption { 473 // Be safe with the size of 'NameLen' because we don't statically check if 474 // the size will fit in the field; the struct size won't decrease with a 475 // shorter type anyway. 476 size_t NameLen; 477 const char *NameStr; 478 const short *Members; 479 const short *SubGroups; 480 481 StringRef getName() const { 482 return StringRef(NameStr, NameLen); 483 } 484 }; 485 486 #define GET_DIAG_ARRAYS 487 #include "clang/Basic/DiagnosticGroups.inc" 488 #undef GET_DIAG_ARRAYS 489 490 // Second the table of options, sorted by name for fast binary lookup. 491 static const WarningOption OptionTable[] = { 492 #define GET_DIAG_TABLE 493 #include "clang/Basic/DiagnosticGroups.inc" 494 #undef GET_DIAG_TABLE 495 }; 496 static const size_t OptionTableSize = 497 sizeof(OptionTable) / sizeof(OptionTable[0]); 498 499 static bool WarningOptionCompare(const WarningOption &LHS, 500 const WarningOption &RHS) { 501 return LHS.getName() < RHS.getName(); 502 } 503 504 /// getWarningOptionForDiag - Return the lowest-level warning option that 505 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 506 /// the diagnostic, this returns null. 507 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 508 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 509 return OptionTable[Info->getOptionGroupIndex()].getName(); 510 return StringRef(); 511 } 512 513 void DiagnosticIDs::getDiagnosticsInGroup( 514 const WarningOption *Group, 515 llvm::SmallVectorImpl<diag::kind> &Diags) const 516 { 517 // Add the members of the option diagnostic set. 518 if (const short *Member = Group->Members) { 519 for (; *Member != -1; ++Member) 520 Diags.push_back(*Member); 521 } 522 523 // Add the members of the subgroups. 524 if (const short *SubGroups = Group->SubGroups) { 525 for (; *SubGroups != (short)-1; ++SubGroups) 526 getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags); 527 } 528 } 529 530 bool DiagnosticIDs::getDiagnosticsInGroup( 531 StringRef Group, 532 llvm::SmallVectorImpl<diag::kind> &Diags) const 533 { 534 WarningOption Key = { Group.size(), Group.data(), 0, 0 }; 535 const WarningOption *Found = 536 std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, 537 WarningOptionCompare); 538 if (Found == OptionTable + OptionTableSize || 539 Found->getName() != Group) 540 return true; // Option not found. 541 542 getDiagnosticsInGroup(Found, Diags); 543 return false; 544 } 545 546 void DiagnosticIDs::getAllDiagnostics( 547 llvm::SmallVectorImpl<diag::kind> &Diags) const { 548 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 549 Diags.push_back(StaticDiagInfo[i].DiagID); 550 } 551 552 StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) { 553 StringRef Best; 554 unsigned BestDistance = Group.size() + 1; // Sanity threshold. 555 for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize; 556 i != e; ++i) { 557 // Don't suggest ignored warning flags. 558 if (!i->Members && !i->SubGroups) 559 continue; 560 561 unsigned Distance = i->getName().edit_distance(Group, true, BestDistance); 562 if (Distance == BestDistance) { 563 // Two matches with the same distance, don't prefer one over the other. 564 Best = ""; 565 } else if (Distance < BestDistance) { 566 // This is a better match. 567 Best = i->getName(); 568 BestDistance = Distance; 569 } 570 } 571 572 return Best; 573 } 574 575 /// ProcessDiag - This is the method used to report a diagnostic that is 576 /// finally fully formed. 577 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 578 Diagnostic Info(&Diag); 579 580 if (Diag.SuppressAllDiagnostics) 581 return false; 582 583 assert(Diag.getClient() && "DiagnosticClient not set!"); 584 585 // Figure out the diagnostic level of this message. 586 DiagnosticIDs::Level DiagLevel; 587 unsigned DiagID = Info.getID(); 588 589 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 590 // Handle custom diagnostics, which cannot be mapped. 591 DiagLevel = CustomDiagInfo->getLevel(DiagID); 592 } else { 593 // Get the class of the diagnostic. If this is a NOTE, map it onto whatever 594 // the diagnostic level was for the previous diagnostic so that it is 595 // filtered the same as the previous diagnostic. 596 unsigned DiagClass = getBuiltinDiagClass(DiagID); 597 if (DiagClass == CLASS_NOTE) { 598 DiagLevel = DiagnosticIDs::Note; 599 } else { 600 DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(), 601 Diag); 602 } 603 } 604 605 if (DiagLevel != DiagnosticIDs::Note) { 606 // Record that a fatal error occurred only when we see a second 607 // non-note diagnostic. This allows notes to be attached to the 608 // fatal error, but suppresses any diagnostics that follow those 609 // notes. 610 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 611 Diag.FatalErrorOccurred = true; 612 613 Diag.LastDiagLevel = DiagLevel; 614 } 615 616 // Update counts for DiagnosticErrorTrap even if a fatal error occurred. 617 if (DiagLevel >= DiagnosticIDs::Error) { 618 ++Diag.TrapNumErrorsOccurred; 619 if (isUnrecoverable(DiagID)) 620 ++Diag.TrapNumUnrecoverableErrorsOccurred; 621 } 622 623 // If a fatal error has already been emitted, silence all subsequent 624 // diagnostics. 625 if (Diag.FatalErrorOccurred) { 626 if (DiagLevel >= DiagnosticIDs::Error && 627 Diag.Client->IncludeInDiagnosticCounts()) { 628 ++Diag.NumErrors; 629 ++Diag.NumErrorsSuppressed; 630 } 631 632 return false; 633 } 634 635 // If the client doesn't care about this message, don't issue it. If this is 636 // a note and the last real diagnostic was ignored, ignore it too. 637 if (DiagLevel == DiagnosticIDs::Ignored || 638 (DiagLevel == DiagnosticIDs::Note && 639 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 640 return false; 641 642 if (DiagLevel >= DiagnosticIDs::Error) { 643 if (isUnrecoverable(DiagID)) 644 Diag.UnrecoverableErrorOccurred = true; 645 646 if (Diag.Client->IncludeInDiagnosticCounts()) { 647 Diag.ErrorOccurred = true; 648 ++Diag.NumErrors; 649 } 650 651 // If we've emitted a lot of errors, emit a fatal error instead of it to 652 // stop a flood of bogus errors. 653 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 654 DiagLevel == DiagnosticIDs::Error) { 655 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 656 return false; 657 } 658 } 659 660 // Finally, report it. 661 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 662 if (Diag.Client->IncludeInDiagnosticCounts()) { 663 if (DiagLevel == DiagnosticIDs::Warning) 664 ++Diag.NumWarnings; 665 } 666 667 Diag.CurDiagID = ~0U; 668 669 return true; 670 } 671 672 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 673 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 674 // Custom diagnostics. 675 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 676 } 677 678 // Only errors may be unrecoverable. 679 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 680 return false; 681 682 if (DiagID == diag::err_unavailable || 683 DiagID == diag::err_unavailable_message) 684 return false; 685 686 // Currently we consider all ARC errors as recoverable. 687 if (isARCDiagnostic(DiagID)) 688 return false; 689 690 return true; 691 } 692 693 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 694 unsigned cat = getCategoryNumberForDiag(DiagID); 695 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 696 } 697 698