1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Diagnostic IDs-related interfaces.
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTDiagnostic.h"
15 #include "clang/Analysis/AnalysisDiagnostic.h"
16 #include "clang/Basic/DiagnosticIDs.h"
17 #include "clang/Basic/DiagnosticCategories.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "clang/Driver/DriverDiagnostic.h"
20 #include "clang/Frontend/FrontendDiagnostic.h"
21 #include "clang/Lex/LexDiagnostic.h"
22 #include "clang/Parse/ParseDiagnostic.h"
23 #include "clang/Sema/SemaDiagnostic.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/Support/ErrorHandling.h"
28 using namespace clang;
30 //===----------------------------------------------------------------------===//
31 // Builtin Diagnostic information
32 //===----------------------------------------------------------------------===//
36 // Diagnostic classes.
40 CLASS_EXTENSION = 0x03,
44 struct StaticDiagInfoRec {
45 unsigned short DiagID;
49 unsigned AccessControl : 1;
50 unsigned WarnNoWerror : 1;
51 unsigned WarnShowInSystemHeader : 1;
52 unsigned Category : 5;
55 uint8_t OptionGroupLen;
57 uint16_t DescriptionLen;
58 uint16_t BriefExplanationLen;
59 uint16_t FullExplanationLen;
62 const char *OptionGroupStr;
64 const char *DescriptionStr;
65 const char *BriefExplanationStr;
66 const char *FullExplanationStr;
68 StringRef getName() const {
69 return StringRef(NameStr, NameLen);
71 StringRef getOptionGroup() const {
72 return StringRef(OptionGroupStr, OptionGroupLen);
75 StringRef getDescription() const {
76 return StringRef(DescriptionStr, DescriptionLen);
78 StringRef getBriefExplanation() const {
79 return StringRef(BriefExplanationStr, BriefExplanationLen);
81 StringRef getFullExplanation() const {
82 return StringRef(FullExplanationStr, FullExplanationLen);
85 bool operator<(const StaticDiagInfoRec &RHS) const {
86 return DiagID < RHS.DiagID;
90 struct StaticDiagNameIndexRec {
92 unsigned short DiagID;
95 StringRef getName() const {
96 return StringRef(NameStr, NameLen);
99 bool operator<(const StaticDiagNameIndexRec &RHS) const {
100 return getName() < RHS.getName();
103 bool operator==(const StaticDiagNameIndexRec &RHS) const {
104 return getName() == RHS.getName();
108 template <size_t SizeOfStr, typename FieldType>
109 class StringSizerHelper {
110 char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
112 enum { Size = SizeOfStr };
115 } // namespace anonymous
117 #define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size
119 static const StaticDiagInfoRec StaticDiagInfo[] = {
120 #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
121 SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER, \
122 CATEGORY,BRIEF,FULL) \
123 { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, \
124 NOWERROR, SHOWINSYSHEADER, CATEGORY, \
125 STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t), \
126 STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t), \
127 STR_SIZE(FULL, uint16_t), \
128 #ENUM, GROUP, DESC, BRIEF, FULL },
129 #include "clang/Basic/DiagnosticCommonKinds.inc"
130 #include "clang/Basic/DiagnosticDriverKinds.inc"
131 #include "clang/Basic/DiagnosticFrontendKinds.inc"
132 #include "clang/Basic/DiagnosticLexKinds.inc"
133 #include "clang/Basic/DiagnosticParseKinds.inc"
134 #include "clang/Basic/DiagnosticASTKinds.inc"
135 #include "clang/Basic/DiagnosticSemaKinds.inc"
136 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
138 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
141 static const unsigned StaticDiagInfoSize =
142 sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
144 /// To be sorted before first use (since it's splitted among multiple files)
145 static const StaticDiagNameIndexRec StaticDiagNameIndex[] = {
146 #define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
147 #include "clang/Basic/DiagnosticIndexName.inc"
148 #undef DIAG_NAME_INDEX
152 static const unsigned StaticDiagNameIndexSize =
153 sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
155 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
156 /// or null if the ID is invalid.
157 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
158 // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
160 static bool IsFirst = true;
162 for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
163 assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
164 "Diag ID conflict, the enums at the start of clang::diag (in "
165 "DiagnosticIDs.h) probably need to be increased");
167 assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
168 "Improperly sorted diag info");
174 // Search the diagnostic table with a binary search.
175 StaticDiagInfoRec Find = { static_cast<unsigned short>(DiagID),
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
178 const StaticDiagInfoRec *Found =
179 std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find);
180 if (Found == StaticDiagInfo + StaticDiagInfoSize ||
181 Found->DiagID != DiagID)
187 static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
188 DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make(
189 diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false);
191 if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
192 Info.setMapping((diag::Mapping) StaticInfo->Mapping);
194 if (StaticInfo->WarnNoWerror) {
195 assert(Info.getMapping() == diag::MAP_WARNING &&
196 "Unexpected mapping with no-Werror bit!");
197 Info.setNoWarningAsError(true);
200 if (StaticInfo->WarnShowInSystemHeader) {
201 assert(Info.getMapping() == diag::MAP_WARNING &&
202 "Unexpected mapping with show-in-system-header bit!");
203 Info.setShowInSystemHeader(true);
210 /// getWarningOptionForDiag - Return the lowest-level warning option that
211 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
212 /// the diagnostic, this returns null.
213 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
214 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
215 return Info->getOptionGroup();
219 /// getCategoryNumberForDiag - Return the category number that a specified
220 /// DiagID belongs to, or 0 if no category.
221 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
222 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
223 return Info->Category;
228 // The diagnostic category names.
229 struct StaticDiagCategoryRec {
233 StringRef getName() const {
234 return StringRef(NameStr, NameLen);
239 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
240 // particularly clean, but for now we just implement this method here so we can
241 // access GetDefaultDiagMapping.
242 DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo(
245 std::pair<iterator, bool> Result = DiagMap.insert(
246 std::make_pair(Diag, DiagnosticMappingInfo()));
248 // Initialize the entry if we added it.
250 Result.first->second = GetDefaultDiagMappingInfo(Diag);
252 return Result.first->second;
255 static const StaticDiagCategoryRec CategoryNameTable[] = {
256 #define GET_CATEGORY_TABLE
257 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
258 #include "clang/Basic/DiagnosticGroups.inc"
259 #undef GET_CATEGORY_TABLE
263 /// getNumberOfCategories - Return the number of categories
264 unsigned DiagnosticIDs::getNumberOfCategories() {
265 return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
268 /// getCategoryNameFromID - Given a category ID, return the name of the
269 /// category, an empty string if CategoryID is zero, or null if CategoryID is
271 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
272 if (CategoryID >= getNumberOfCategories())
274 return CategoryNameTable[CategoryID].getName();
279 DiagnosticIDs::SFINAEResponse
280 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
281 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
282 if (Info->AccessControl)
283 return SFINAE_AccessControl;
286 return SFINAE_Report;
288 if (Info->Class == CLASS_ERROR)
289 return SFINAE_SubstitutionFailure;
291 // Suppress notes, warnings, and extensions;
292 return SFINAE_Suppress;
295 return SFINAE_Report;
298 /// getName - Given a diagnostic ID, return its name
299 StringRef DiagnosticIDs::getName(unsigned DiagID) {
300 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
301 return Info->getName();
305 /// getIdFromName - Given a diagnostic name, return its ID, or 0
306 unsigned DiagnosticIDs::getIdFromName(StringRef Name) {
307 const StaticDiagNameIndexRec *StaticDiagNameIndexEnd =
308 StaticDiagNameIndex + StaticDiagNameIndexSize;
310 if (Name.empty()) { return diag::DIAG_UPPER_LIMIT; }
312 assert(Name.size() == static_cast<uint8_t>(Name.size()) &&
314 StaticDiagNameIndexRec Find = { Name.data(), 0,
315 static_cast<uint8_t>(Name.size()) };
317 const StaticDiagNameIndexRec *Found =
318 std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find);
319 if (Found == StaticDiagNameIndexEnd ||
320 Found->getName() != Name)
321 return diag::DIAG_UPPER_LIMIT;
323 return Found->DiagID;
326 /// getBriefExplanation - Given a diagnostic ID, return a brief explanation
328 StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) {
329 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
330 return Info->getBriefExplanation();
334 /// getFullExplanation - Given a diagnostic ID, return a full explanation
336 StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) {
337 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
338 return Info->getFullExplanation();
342 /// getBuiltinDiagClass - Return the class field of the diagnostic.
344 static unsigned getBuiltinDiagClass(unsigned DiagID) {
345 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
350 //===----------------------------------------------------------------------===//
352 //===----------------------------------------------------------------------===//
354 llvm::StringRef DiagnosticIDs::diag_iterator::getDiagName() const {
355 return static_cast<const StaticDiagNameIndexRec*>(impl)->getName();
358 unsigned DiagnosticIDs::diag_iterator::getDiagID() const {
359 return static_cast<const StaticDiagNameIndexRec*>(impl)->DiagID;
362 DiagnosticIDs::diag_iterator &DiagnosticIDs::diag_iterator::operator++() {
363 const StaticDiagNameIndexRec* ptr =
364 static_cast<const StaticDiagNameIndexRec*>(impl);;
370 DiagnosticIDs::diag_iterator DiagnosticIDs::diags_begin() {
371 return DiagnosticIDs::diag_iterator(StaticDiagNameIndex);
374 DiagnosticIDs::diag_iterator DiagnosticIDs::diags_end() {
375 return DiagnosticIDs::diag_iterator(StaticDiagNameIndex +
376 StaticDiagNameIndexSize);
379 //===----------------------------------------------------------------------===//
380 // Custom Diagnostic information
381 //===----------------------------------------------------------------------===//
385 class CustomDiagInfo {
386 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
387 std::vector<DiagDesc> DiagInfo;
388 std::map<DiagDesc, unsigned> DiagIDs;
391 /// getDescription - Return the description of the specified custom
393 StringRef getDescription(unsigned DiagID) const {
394 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
395 "Invalid diagnosic ID");
396 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
399 /// getLevel - Return the level of the specified custom diagnostic.
400 DiagnosticIDs::Level getLevel(unsigned DiagID) const {
401 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
402 "Invalid diagnosic ID");
403 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
406 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
407 DiagnosticIDs &Diags) {
408 DiagDesc D(L, Message);
409 // Check to see if it already exists.
410 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
411 if (I != DiagIDs.end() && I->first == D)
414 // If not, assign a new ID.
415 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
416 DiagIDs.insert(std::make_pair(D, ID));
417 DiagInfo.push_back(D);
422 } // end diag namespace
423 } // end clang namespace
426 //===----------------------------------------------------------------------===//
427 // Common Diagnostic implementation
428 //===----------------------------------------------------------------------===//
430 DiagnosticIDs::DiagnosticIDs() {
434 DiagnosticIDs::~DiagnosticIDs() {
435 delete CustomDiagInfo;
438 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
439 /// and level. If this is the first request for this diagnosic, it is
440 /// registered and created, otherwise the existing ID is returned.
441 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) {
442 if (CustomDiagInfo == 0)
443 CustomDiagInfo = new diag::CustomDiagInfo();
444 return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
448 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
449 /// level of the specified diagnostic ID is a Warning or Extension.
450 /// This only works on builtin diagnostics, not custom ones, and is not legal to
452 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
453 return DiagID < diag::DIAG_UPPER_LIMIT &&
454 getBuiltinDiagClass(DiagID) != CLASS_ERROR;
457 /// \brief Determine whether the given built-in diagnostic ID is a
459 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
460 return DiagID < diag::DIAG_UPPER_LIMIT &&
461 getBuiltinDiagClass(DiagID) == CLASS_NOTE;
464 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
465 /// ID is for an extension of some sort. This also returns EnabledByDefault,
466 /// which is set to indicate whether the diagnostic is ignored by default (in
467 /// which case -pedantic enables it) or treated as a warning/error by default.
469 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
470 bool &EnabledByDefault) {
471 if (DiagID >= diag::DIAG_UPPER_LIMIT ||
472 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
476 GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE;
480 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
481 if (DiagID >= diag::DIAG_UPPER_LIMIT)
484 return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
487 /// getDescription - Given a diagnostic ID, return a description of the
489 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
490 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
491 return Info->getDescription();
492 return CustomDiagInfo->getDescription(DiagID);
495 /// getDiagnosticLevel - Based on the way the client configured the
496 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
497 /// by consumable the DiagnosticClient.
499 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
500 const DiagnosticsEngine &Diag) const {
501 // Handle custom diagnostics, which cannot be mapped.
502 if (DiagID >= diag::DIAG_UPPER_LIMIT)
503 return CustomDiagInfo->getLevel(DiagID);
505 unsigned DiagClass = getBuiltinDiagClass(DiagID);
506 assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
507 return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
510 /// \brief Based on the way the client configured the Diagnostic
511 /// object, classify the specified diagnostic ID into a Level, consumable by
512 /// the DiagnosticClient.
514 /// \param Loc The source location we are interested in finding out the
515 /// diagnostic state. Can be null in order to query the latest state.
517 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
519 const DiagnosticsEngine &Diag) const {
520 // Specific non-error diagnostics may be mapped to various levels from ignored
521 // to error. Errors can only be mapped to fatal.
522 DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
524 DiagnosticsEngine::DiagStatePointsTy::iterator
525 Pos = Diag.GetDiagStatePointForLoc(Loc);
526 DiagnosticsEngine::DiagState *State = Pos->State;
528 // Get the mapping information, or compute it lazily.
529 DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
532 switch (MappingInfo.getMapping()) {
533 default: llvm_unreachable("Unknown mapping!");
534 case diag::MAP_IGNORE:
535 Result = DiagnosticIDs::Ignored;
537 case diag::MAP_WARNING:
538 Result = DiagnosticIDs::Warning;
540 case diag::MAP_ERROR:
541 Result = DiagnosticIDs::Error;
543 case diag::MAP_FATAL:
544 Result = DiagnosticIDs::Fatal;
548 // Upgrade ignored diagnostics if -Weverything is enabled.
549 if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
550 !MappingInfo.isUser())
551 Result = DiagnosticIDs::Warning;
553 // Ignore -pedantic diagnostics inside __extension__ blocks.
554 // (The diagnostics controlled by -pedantic are the extension diagnostics
555 // that are not enabled by default.)
556 bool EnabledByDefault;
557 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
558 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
559 return DiagnosticIDs::Ignored;
561 // For extension diagnostics that haven't been explicitly mapped, check if we
562 // should upgrade the diagnostic.
563 if (IsExtensionDiag && !MappingInfo.isUser()) {
564 switch (Diag.ExtBehavior) {
565 case DiagnosticsEngine::Ext_Ignore:
567 case DiagnosticsEngine::Ext_Warn:
568 // Upgrade ignored diagnostics to warnings.
569 if (Result == DiagnosticIDs::Ignored)
570 Result = DiagnosticIDs::Warning;
572 case DiagnosticsEngine::Ext_Error:
573 // Upgrade ignored or warning diagnostics to errors.
574 if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning)
575 Result = DiagnosticIDs::Error;
580 // At this point, ignored errors can no longer be upgraded.
581 if (Result == DiagnosticIDs::Ignored)
584 // Honor -w, which is lower in priority than pedantic-errors, but higher than
586 if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings)
587 return DiagnosticIDs::Ignored;
589 // If -Werror is enabled, map warnings to errors unless explicitly disabled.
590 if (Result == DiagnosticIDs::Warning) {
591 if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError())
592 Result = DiagnosticIDs::Error;
595 // If -Wfatal-errors is enabled, map errors to fatal unless explicity
597 if (Result == DiagnosticIDs::Error) {
598 if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal())
599 Result = DiagnosticIDs::Fatal;
602 // If we are in a system header, we ignore it. We look at the diagnostic class
603 // because we also want to ignore extensions and warnings in -Werror and
604 // -pedantic-errors modes, which *map* warnings/extensions to errors.
605 if (Result >= DiagnosticIDs::Warning &&
606 DiagClass != CLASS_ERROR &&
607 // Custom diagnostics always are emitted in system headers.
608 DiagID < diag::DIAG_UPPER_LIMIT &&
609 !MappingInfo.hasShowInSystemHeader() &&
610 Diag.SuppressSystemWarnings &&
612 Diag.getSourceManager().isInSystemHeader(
613 Diag.getSourceManager().getExpansionLoc(Loc)))
614 return DiagnosticIDs::Ignored;
619 struct clang::WarningOption {
620 // Be safe with the size of 'NameLen' because we don't statically check if
621 // the size will fit in the field; the struct size won't decrease with a
622 // shorter type anyway.
625 const short *Members;
626 const short *SubGroups;
628 StringRef getName() const {
629 return StringRef(NameStr, NameLen);
633 #define GET_DIAG_ARRAYS
634 #include "clang/Basic/DiagnosticGroups.inc"
635 #undef GET_DIAG_ARRAYS
637 // Second the table of options, sorted by name for fast binary lookup.
638 static const WarningOption OptionTable[] = {
639 #define GET_DIAG_TABLE
640 #include "clang/Basic/DiagnosticGroups.inc"
641 #undef GET_DIAG_TABLE
643 static const size_t OptionTableSize =
644 sizeof(OptionTable) / sizeof(OptionTable[0]);
646 static bool WarningOptionCompare(const WarningOption &LHS,
647 const WarningOption &RHS) {
648 return LHS.getName() < RHS.getName();
651 void DiagnosticIDs::getDiagnosticsInGroup(
652 const WarningOption *Group,
653 llvm::SmallVectorImpl<diag::kind> &Diags) const
655 // Add the members of the option diagnostic set.
656 if (const short *Member = Group->Members) {
657 for (; *Member != -1; ++Member)
658 Diags.push_back(*Member);
661 // Add the members of the subgroups.
662 if (const short *SubGroups = Group->SubGroups) {
663 for (; *SubGroups != (short)-1; ++SubGroups)
664 getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags);
668 bool DiagnosticIDs::getDiagnosticsInGroup(
670 llvm::SmallVectorImpl<diag::kind> &Diags) const
672 WarningOption Key = { Group.size(), Group.data(), 0, 0 };
673 const WarningOption *Found =
674 std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
675 WarningOptionCompare);
676 if (Found == OptionTable + OptionTableSize ||
677 Found->getName() != Group)
678 return true; // Option not found.
680 getDiagnosticsInGroup(Found, Diags);
684 /// ProcessDiag - This is the method used to report a diagnostic that is
685 /// finally fully formed.
686 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
687 Diagnostic Info(&Diag);
689 if (Diag.SuppressAllDiagnostics)
692 assert(Diag.getClient() && "DiagnosticClient not set!");
694 // Figure out the diagnostic level of this message.
695 DiagnosticIDs::Level DiagLevel;
696 unsigned DiagID = Info.getID();
698 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
699 // Handle custom diagnostics, which cannot be mapped.
700 DiagLevel = CustomDiagInfo->getLevel(DiagID);
702 // Get the class of the diagnostic. If this is a NOTE, map it onto whatever
703 // the diagnostic level was for the previous diagnostic so that it is
704 // filtered the same as the previous diagnostic.
705 unsigned DiagClass = getBuiltinDiagClass(DiagID);
706 if (DiagClass == CLASS_NOTE) {
707 DiagLevel = DiagnosticIDs::Note;
709 DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
714 if (DiagLevel != DiagnosticIDs::Note) {
715 // Record that a fatal error occurred only when we see a second
716 // non-note diagnostic. This allows notes to be attached to the
717 // fatal error, but suppresses any diagnostics that follow those
719 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
720 Diag.FatalErrorOccurred = true;
722 Diag.LastDiagLevel = DiagLevel;
725 // Update counts for DiagnosticErrorTrap even if a fatal error occurred.
726 if (DiagLevel >= DiagnosticIDs::Error) {
727 ++Diag.TrapNumErrorsOccurred;
728 if (isUnrecoverable(DiagID))
729 ++Diag.TrapNumUnrecoverableErrorsOccurred;
732 // If a fatal error has already been emitted, silence all subsequent
734 if (Diag.FatalErrorOccurred) {
735 if (DiagLevel >= DiagnosticIDs::Error &&
736 Diag.Client->IncludeInDiagnosticCounts()) {
738 ++Diag.NumErrorsSuppressed;
744 // If the client doesn't care about this message, don't issue it. If this is
745 // a note and the last real diagnostic was ignored, ignore it too.
746 if (DiagLevel == DiagnosticIDs::Ignored ||
747 (DiagLevel == DiagnosticIDs::Note &&
748 Diag.LastDiagLevel == DiagnosticIDs::Ignored))
751 if (DiagLevel >= DiagnosticIDs::Error) {
752 if (isUnrecoverable(DiagID))
753 Diag.UnrecoverableErrorOccurred = true;
755 if (Diag.Client->IncludeInDiagnosticCounts()) {
756 Diag.ErrorOccurred = true;
760 // If we've emitted a lot of errors, emit a fatal error instead of it to
761 // stop a flood of bogus errors.
762 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
763 DiagLevel == DiagnosticIDs::Error) {
764 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
769 // If we have any Fix-Its, make sure that all of the Fix-Its point into
770 // source locations that aren't macro expansions. If any point into macro
771 // expansions, remove all of the Fix-Its.
772 for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) {
773 const FixItHint &FixIt = Diag.FixItHints[I];
774 if (FixIt.RemoveRange.isInvalid() ||
775 FixIt.RemoveRange.getBegin().isMacroID() ||
776 FixIt.RemoveRange.getEnd().isMacroID()) {
777 Diag.NumFixItHints = 0;
782 // Finally, report it.
783 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
784 if (Diag.Client->IncludeInDiagnosticCounts()) {
785 if (DiagLevel == DiagnosticIDs::Warning)
789 Diag.CurDiagID = ~0U;
794 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
795 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
796 // Custom diagnostics.
797 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
800 // Only errors may be unrecoverable.
801 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
804 if (DiagID == diag::err_unavailable ||
805 DiagID == diag::err_unavailable_message)
808 // Currently we consider all ARC errors as recoverable.
809 if (getCategoryNumberForDiag(DiagID) ==
810 diag::DiagCat_Automatic_Reference_Counting_Issue)