]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / Basic / DiagnosticIDs.cpp
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/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"
26
27 #include <map>
28 using namespace clang;
29
30 //===----------------------------------------------------------------------===//
31 // Builtin Diagnostic information
32 //===----------------------------------------------------------------------===//
33
34 namespace {
35
36 // Diagnostic classes.
37 enum {
38   CLASS_NOTE       = 0x01,
39   CLASS_WARNING    = 0x02,
40   CLASS_EXTENSION  = 0x03,
41   CLASS_ERROR      = 0x04
42 };
43
44 struct StaticDiagInfoRec {
45   unsigned short DiagID;
46   unsigned Mapping : 3;
47   unsigned Class : 3;
48   unsigned SFINAE : 1;
49   unsigned AccessControl : 1;
50   unsigned WarnNoWerror : 1;
51   unsigned WarnShowInSystemHeader : 1;
52   unsigned Category : 5;
53
54   uint8_t  NameLen;
55   uint8_t  OptionGroupLen;
56
57   uint16_t DescriptionLen;
58   uint16_t BriefExplanationLen;
59   uint16_t FullExplanationLen;
60
61   const char *NameStr;
62   const char *OptionGroupStr;
63
64   const char *DescriptionStr;
65   const char *BriefExplanationStr;
66   const char *FullExplanationStr;
67
68   StringRef getName() const {
69     return StringRef(NameStr, NameLen);
70   }
71   StringRef getOptionGroup() const {
72     return StringRef(OptionGroupStr, OptionGroupLen);
73   }
74
75   StringRef getDescription() const {
76     return StringRef(DescriptionStr, DescriptionLen);
77   }
78   StringRef getBriefExplanation() const {
79     return StringRef(BriefExplanationStr, BriefExplanationLen);
80   }
81   StringRef getFullExplanation() const {
82     return StringRef(FullExplanationStr, FullExplanationLen);
83   }
84
85   bool operator<(const StaticDiagInfoRec &RHS) const {
86     return DiagID < RHS.DiagID;
87   }
88 };
89
90 struct StaticDiagNameIndexRec {
91   const char *NameStr;
92   unsigned short DiagID;
93   uint8_t NameLen;
94
95   StringRef getName() const {
96     return StringRef(NameStr, NameLen);
97   }
98
99   bool operator<(const StaticDiagNameIndexRec &RHS) const {
100     return getName() < RHS.getName();
101   }
102   
103   bool operator==(const StaticDiagNameIndexRec &RHS) const {
104     return getName() == RHS.getName();
105   }
106 };
107
108 template <size_t SizeOfStr, typename FieldType>
109 class StringSizerHelper {
110   char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
111 public:
112   enum { Size = SizeOfStr };
113 };
114
115 } // namespace anonymous
116
117 #define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size 
118
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"
137 #undef DIAG
138   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
139 };
140
141 static const unsigned StaticDiagInfoSize =
142   sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
143
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
149   { 0, 0, 0 }
150 };
151
152 static const unsigned StaticDiagNameIndexSize =
153   sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
154
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.
159 #ifndef NDEBUG
160   static bool IsFirst = true;
161   if (IsFirst) {
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");
166
167       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
168              "Improperly sorted diag info");
169     }
170     IsFirst = false;
171   }
172 #endif
173
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};
177
178   const StaticDiagInfoRec *Found =
179     std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find);
180   if (Found == StaticDiagInfo + StaticDiagInfoSize ||
181       Found->DiagID != DiagID)
182     return 0;
183
184   return Found;
185 }
186
187 static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
188   DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make(
189     diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false);
190
191   if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
192     Info.setMapping((diag::Mapping) StaticInfo->Mapping);
193
194     if (StaticInfo->WarnNoWerror) {
195       assert(Info.getMapping() == diag::MAP_WARNING &&
196              "Unexpected mapping with no-Werror bit!");
197       Info.setNoWarningAsError(true);
198     }
199
200     if (StaticInfo->WarnShowInSystemHeader) {
201       assert(Info.getMapping() == diag::MAP_WARNING &&
202              "Unexpected mapping with show-in-system-header bit!");
203       Info.setShowInSystemHeader(true);
204     }
205   }
206
207   return Info;
208 }
209
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();
216   return StringRef();
217 }
218
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;
224   return 0;
225 }
226
227 namespace {
228   // The diagnostic category names.
229   struct StaticDiagCategoryRec {
230     const char *NameStr;
231     uint8_t NameLen;
232
233     StringRef getName() const {
234       return StringRef(NameStr, NameLen);
235     }
236   };
237 }
238
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(
243   diag::kind Diag)
244 {
245   std::pair<iterator, bool> Result = DiagMap.insert(
246     std::make_pair(Diag, DiagnosticMappingInfo()));
247
248   // Initialize the entry if we added it.
249   if (Result.second)
250     Result.first->second = GetDefaultDiagMappingInfo(Diag);
251
252   return Result.first->second;
253 }
254
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
260   { 0, 0 }
261 };
262
263 /// getNumberOfCategories - Return the number of categories
264 unsigned DiagnosticIDs::getNumberOfCategories() {
265   return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
266 }
267
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
270 /// invalid.
271 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
272   if (CategoryID >= getNumberOfCategories())
273    return StringRef();
274   return CategoryNameTable[CategoryID].getName();
275 }
276
277
278
279 DiagnosticIDs::SFINAEResponse 
280 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
281   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
282     if (Info->AccessControl)
283       return SFINAE_AccessControl;
284     
285     if (!Info->SFINAE)
286       return SFINAE_Report;
287
288     if (Info->Class == CLASS_ERROR)
289       return SFINAE_SubstitutionFailure;
290     
291     // Suppress notes, warnings, and extensions;
292     return SFINAE_Suppress;
293   }
294   
295   return SFINAE_Report;
296 }
297
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();
302   return StringRef();
303 }
304
305 /// getIdFromName - Given a diagnostic name, return its ID, or 0
306 unsigned DiagnosticIDs::getIdFromName(StringRef Name) {
307   const StaticDiagNameIndexRec *StaticDiagNameIndexEnd =
308     StaticDiagNameIndex + StaticDiagNameIndexSize;
309   
310   if (Name.empty()) { return diag::DIAG_UPPER_LIMIT; }
311   
312   assert(Name.size() == static_cast<uint8_t>(Name.size()) &&
313          "Name is too long");
314   StaticDiagNameIndexRec Find = { Name.data(), 0,
315                                   static_cast<uint8_t>(Name.size()) };
316   
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;
322   
323   return Found->DiagID;
324 }
325
326 /// getBriefExplanation - Given a diagnostic ID, return a brief explanation
327 /// of the issue
328 StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) {
329   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
330     return Info->getBriefExplanation();
331   return StringRef();
332 }
333
334 /// getFullExplanation - Given a diagnostic ID, return a full explanation
335 /// of the issue
336 StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) {
337   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
338     return Info->getFullExplanation();
339   return StringRef();
340 }
341
342 /// getBuiltinDiagClass - Return the class field of the diagnostic.
343 ///
344 static unsigned getBuiltinDiagClass(unsigned DiagID) {
345   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
346     return Info->Class;
347   return ~0U;
348 }
349
350 //===----------------------------------------------------------------------===//
351 // diag_iterator
352 //===----------------------------------------------------------------------===//
353
354 llvm::StringRef DiagnosticIDs::diag_iterator::getDiagName() const {
355   return static_cast<const StaticDiagNameIndexRec*>(impl)->getName();
356 }
357
358 unsigned DiagnosticIDs::diag_iterator::getDiagID() const {
359   return static_cast<const StaticDiagNameIndexRec*>(impl)->DiagID;
360 }
361
362 DiagnosticIDs::diag_iterator &DiagnosticIDs::diag_iterator::operator++() {
363   const StaticDiagNameIndexRec* ptr =
364     static_cast<const StaticDiagNameIndexRec*>(impl);;
365   ++ptr;
366   impl = ptr;
367   return *this;
368 }
369
370 DiagnosticIDs::diag_iterator DiagnosticIDs::diags_begin() {
371   return DiagnosticIDs::diag_iterator(StaticDiagNameIndex);
372 }
373
374 DiagnosticIDs::diag_iterator DiagnosticIDs::diags_end() {
375   return DiagnosticIDs::diag_iterator(StaticDiagNameIndex +
376                                       StaticDiagNameIndexSize);
377 }
378
379 //===----------------------------------------------------------------------===//
380 // Custom Diagnostic information
381 //===----------------------------------------------------------------------===//
382
383 namespace clang {
384   namespace diag {
385     class CustomDiagInfo {
386       typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
387       std::vector<DiagDesc> DiagInfo;
388       std::map<DiagDesc, unsigned> DiagIDs;
389     public:
390
391       /// getDescription - Return the description of the specified custom
392       /// diagnostic.
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;
397       }
398
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;
404       }
405
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)
412           return I->second;
413
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);
418         return ID;
419       }
420     };
421
422   } // end diag namespace
423 } // end clang namespace
424
425
426 //===----------------------------------------------------------------------===//
427 // Common Diagnostic implementation
428 //===----------------------------------------------------------------------===//
429
430 DiagnosticIDs::DiagnosticIDs() {
431   CustomDiagInfo = 0;
432 }
433
434 DiagnosticIDs::~DiagnosticIDs() {
435   delete CustomDiagInfo;
436 }
437
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);
445 }
446
447
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
451 /// call on NOTEs.
452 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
453   return DiagID < diag::DIAG_UPPER_LIMIT &&
454          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
455 }
456
457 /// \brief Determine whether the given built-in diagnostic ID is a
458 /// Note.
459 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
460   return DiagID < diag::DIAG_UPPER_LIMIT &&
461     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
462 }
463
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.
468 ///
469 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
470                                         bool &EnabledByDefault) {
471   if (DiagID >= diag::DIAG_UPPER_LIMIT ||
472       getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
473     return false;
474   
475   EnabledByDefault =
476     GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE;
477   return true;
478 }
479
480 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
481   if (DiagID >= diag::DIAG_UPPER_LIMIT)
482     return false;
483
484   return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
485 }
486
487 /// getDescription - Given a diagnostic ID, return a description of the
488 /// issue.
489 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
490   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
491     return Info->getDescription();
492   return CustomDiagInfo->getDescription(DiagID);
493 }
494
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.
498 DiagnosticIDs::Level
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);
504
505   unsigned DiagClass = getBuiltinDiagClass(DiagID);
506   assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
507   return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
508 }
509
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.
513 ///
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.
516 DiagnosticIDs::Level
517 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
518                                   SourceLocation Loc,
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;
523
524   DiagnosticsEngine::DiagStatePointsTy::iterator
525     Pos = Diag.GetDiagStatePointForLoc(Loc);
526   DiagnosticsEngine::DiagState *State = Pos->State;
527
528   // Get the mapping information, or compute it lazily.
529   DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
530     (diag::kind)DiagID);
531
532   switch (MappingInfo.getMapping()) {
533   default: llvm_unreachable("Unknown mapping!");
534   case diag::MAP_IGNORE:
535     Result = DiagnosticIDs::Ignored;
536     break;
537   case diag::MAP_WARNING:
538     Result = DiagnosticIDs::Warning;
539     break;
540   case diag::MAP_ERROR:
541     Result = DiagnosticIDs::Error;
542     break;
543   case diag::MAP_FATAL:
544     Result = DiagnosticIDs::Fatal;
545     break;
546   }
547
548   // Upgrade ignored diagnostics if -Weverything is enabled.
549   if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
550       !MappingInfo.isUser())
551     Result = DiagnosticIDs::Warning;
552
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;
560
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:
566       break; 
567     case DiagnosticsEngine::Ext_Warn:
568       // Upgrade ignored diagnostics to warnings.
569       if (Result == DiagnosticIDs::Ignored)
570         Result = DiagnosticIDs::Warning;
571       break;
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;
576       break;
577     }
578   }
579
580   // At this point, ignored errors can no longer be upgraded.
581   if (Result == DiagnosticIDs::Ignored)
582     return Result;
583
584   // Honor -w, which is lower in priority than pedantic-errors, but higher than
585   // -Werror.
586   if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings)
587     return DiagnosticIDs::Ignored;
588
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;
593   }
594
595   // If -Wfatal-errors is enabled, map errors to fatal unless explicity
596   // disabled.
597   if (Result == DiagnosticIDs::Error) {
598     if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal())
599       Result = DiagnosticIDs::Fatal;
600   }
601
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 &&
611       Loc.isValid() &&
612       Diag.getSourceManager().isInSystemHeader(
613           Diag.getSourceManager().getExpansionLoc(Loc)))
614     return DiagnosticIDs::Ignored;
615
616   return Result;
617 }
618
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.
623   size_t NameLen;
624   const char *NameStr;
625   const short *Members;
626   const short *SubGroups;
627
628   StringRef getName() const {
629     return StringRef(NameStr, NameLen);
630   }
631 };
632
633 #define GET_DIAG_ARRAYS
634 #include "clang/Basic/DiagnosticGroups.inc"
635 #undef GET_DIAG_ARRAYS
636
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
642 };
643 static const size_t OptionTableSize =
644 sizeof(OptionTable) / sizeof(OptionTable[0]);
645
646 static bool WarningOptionCompare(const WarningOption &LHS,
647                                  const WarningOption &RHS) {
648   return LHS.getName() < RHS.getName();
649 }
650
651 void DiagnosticIDs::getDiagnosticsInGroup(
652   const WarningOption *Group,
653   llvm::SmallVectorImpl<diag::kind> &Diags) const
654 {
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);
659   }
660
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);
665   }
666 }
667
668 bool DiagnosticIDs::getDiagnosticsInGroup(
669   StringRef Group,
670   llvm::SmallVectorImpl<diag::kind> &Diags) const
671 {
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.
679
680   getDiagnosticsInGroup(Found, Diags);
681   return false;
682 }
683
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);
688
689   if (Diag.SuppressAllDiagnostics)
690     return false;
691
692   assert(Diag.getClient() && "DiagnosticClient not set!");
693
694   // Figure out the diagnostic level of this message.
695   DiagnosticIDs::Level DiagLevel;
696   unsigned DiagID = Info.getID();
697
698   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
699     // Handle custom diagnostics, which cannot be mapped.
700     DiagLevel = CustomDiagInfo->getLevel(DiagID);
701   } else {
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;
708     } else {
709       DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
710                                      Diag);
711     }
712   }
713
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
718     // notes.
719     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
720       Diag.FatalErrorOccurred = true;
721
722     Diag.LastDiagLevel = DiagLevel;
723   }
724
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;
730   }
731
732   // If a fatal error has already been emitted, silence all subsequent
733   // diagnostics.
734   if (Diag.FatalErrorOccurred) {
735     if (DiagLevel >= DiagnosticIDs::Error &&
736         Diag.Client->IncludeInDiagnosticCounts()) {
737       ++Diag.NumErrors;
738       ++Diag.NumErrorsSuppressed;
739     }
740
741     return false;
742   }
743
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))
749     return false;
750
751   if (DiagLevel >= DiagnosticIDs::Error) {
752     if (isUnrecoverable(DiagID))
753       Diag.UnrecoverableErrorOccurred = true;
754     
755     if (Diag.Client->IncludeInDiagnosticCounts()) {
756       Diag.ErrorOccurred = true;
757       ++Diag.NumErrors;
758     }
759
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);
765       return false;
766     }
767   }
768
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;
778       break;
779     }    
780   }
781   
782   // Finally, report it.
783   Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
784   if (Diag.Client->IncludeInDiagnosticCounts()) {
785     if (DiagLevel == DiagnosticIDs::Warning)
786       ++Diag.NumWarnings;
787   }
788
789   Diag.CurDiagID = ~0U;
790
791   return true;
792 }
793
794 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
795   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
796     // Custom diagnostics.
797     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
798   }
799
800   // Only errors may be unrecoverable.
801   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
802     return false;
803
804   if (DiagID == diag::err_unavailable ||
805       DiagID == diag::err_unavailable_message)
806     return false;
807
808   // Currently we consider all ARC errors as recoverable.
809   if (getCategoryNumberForDiag(DiagID) ==
810         diag::DiagCat_Automatic_Reference_Counting_Issue)
811     return false;
812
813   return true;
814 }