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