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