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