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