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