clang  3.8.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),
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 
415  Pos = Diag.GetDiagStatePointForLoc(Loc);
416  DiagnosticsEngine::DiagState *State = Pos->State;
417 
418  // Get the mapping information, or compute it lazily.
419  DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
420 
421  // TODO: Can a null severity really get here?
422  if (Mapping.getSeverity() != diag::Severity())
423  Result = Mapping.getSeverity();
424 
425  // Upgrade ignored diagnostics if -Weverything is enabled.
426  if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored &&
427  !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
428  Result = diag::Severity::Warning;
429 
430  // Ignore -pedantic diagnostics inside __extension__ blocks.
431  // (The diagnostics controlled by -pedantic are the extension diagnostics
432  // that are not enabled by default.)
433  bool EnabledByDefault = false;
434  bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
435  if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
437 
438  // For extension diagnostics that haven't been explicitly mapped, check if we
439  // should upgrade the diagnostic.
440  if (IsExtensionDiag && !Mapping.isUser())
441  Result = std::max(Result, Diag.ExtBehavior);
442 
443  // At this point, ignored errors can no longer be upgraded.
444  if (Result == diag::Severity::Ignored)
445  return Result;
446 
447  // Honor -w, which is lower in priority than pedantic-errors, but higher than
448  // -Werror.
449  if (Result == diag::Severity::Warning && Diag.IgnoreAllWarnings)
451 
452  // If -Werror is enabled, map warnings to errors unless explicitly disabled.
453  if (Result == diag::Severity::Warning) {
454  if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError())
455  Result = diag::Severity::Error;
456  }
457 
458  // If -Wfatal-errors is enabled, map errors to fatal unless explicity
459  // disabled.
460  if (Result == diag::Severity::Error) {
461  if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
462  Result = diag::Severity::Fatal;
463  }
464 
465  // Custom diagnostics always are emitted in system headers.
466  bool ShowInSystemHeader =
467  !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
468 
469  // If we are in a system header, we ignore it. We look at the diagnostic class
470  // because we also want to ignore extensions and warnings in -Werror and
471  // -pedantic-errors modes, which *map* warnings/extensions to errors.
472  if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
474  Diag.getSourceManager().getExpansionLoc(Loc)))
476 
477  return Result;
478 }
479 
480 #define GET_DIAG_ARRAYS
481 #include "clang/Basic/DiagnosticGroups.inc"
482 #undef GET_DIAG_ARRAYS
483 
484 namespace {
485  struct WarningOption {
486  uint16_t NameOffset;
487  uint16_t Members;
488  uint16_t SubGroups;
489 
490  // String is stored with a pascal-style length byte.
491  StringRef getName() const {
492  return StringRef(DiagGroupNames + NameOffset + 1,
493  DiagGroupNames[NameOffset]);
494  }
495  };
496 }
497 
498 // Second the table of options, sorted by name for fast binary lookup.
499 static const WarningOption OptionTable[] = {
500 #define GET_DIAG_TABLE
501 #include "clang/Basic/DiagnosticGroups.inc"
502 #undef GET_DIAG_TABLE
503 };
504 
505 /// getWarningOptionForDiag - Return the lowest-level warning option that
506 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
507 /// the diagnostic, this returns null.
508 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
509  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
510  return OptionTable[Info->getOptionGroupIndex()].getName();
511  return StringRef();
512 }
513 
514 /// Return \c true if any diagnostics were found in this group, even if they
515 /// were filtered out due to having the wrong flavor.
517  const WarningOption *Group,
519  // An empty group is considered to be a warning group: we have empty groups
520  // for GCC compatibility, and GCC does not have remarks.
521  if (!Group->Members && !Group->SubGroups)
522  return Flavor == diag::Flavor::Remark;
523 
524  bool NotFound = true;
525 
526  // Add the members of the option diagnostic set.
527  const int16_t *Member = DiagArrays + Group->Members;
528  for (; *Member != -1; ++Member) {
529  if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
530  NotFound = false;
531  Diags.push_back(*Member);
532  }
533  }
534 
535  // Add the members of the subgroups.
536  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
537  for (; *SubGroups != (int16_t)-1; ++SubGroups)
538  NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
539  Diags);
540 
541  return NotFound;
542 }
543 
544 bool
546  SmallVectorImpl<diag::kind> &Diags) const {
547  auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
548  Group,
549  [](const WarningOption &LHS, StringRef RHS) {
550  return LHS.getName() < RHS;
551  });
552  if (Found == std::end(OptionTable) || Found->getName() != Group)
553  return true; // Option not found.
554 
555  return ::getDiagnosticsInGroup(Flavor, Found, Diags);
556 }
557 
559  SmallVectorImpl<diag::kind> &Diags) const {
560  for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
561  if (StaticDiagInfo[i].getFlavor() == Flavor)
562  Diags.push_back(StaticDiagInfo[i].DiagID);
563 }
564 
566  StringRef Group) {
567  StringRef Best;
568  unsigned BestDistance = Group.size() + 1; // Sanity threshold.
569  for (const WarningOption &O : OptionTable) {
570  // Don't suggest ignored warning flags.
571  if (!O.Members && !O.SubGroups)
572  continue;
573 
574  unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
575  if (Distance > BestDistance)
576  continue;
577 
578  // Don't suggest groups that are not of this kind.
580  if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
581  continue;
582 
583  if (Distance == BestDistance) {
584  // Two matches with the same distance, don't prefer one over the other.
585  Best = "";
586  } else if (Distance < BestDistance) {
587  // This is a better match.
588  Best = O.getName();
589  BestDistance = Distance;
590  }
591  }
592 
593  return Best;
594 }
595 
596 /// ProcessDiag - This is the method used to report a diagnostic that is
597 /// finally fully formed.
598 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
599  Diagnostic Info(&Diag);
600 
601  assert(Diag.getClient() && "DiagnosticClient not set!");
602 
603  // Figure out the diagnostic level of this message.
604  unsigned DiagID = Info.getID();
605  DiagnosticIDs::Level DiagLevel
606  = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
607 
608  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
609  // or diagnostics are suppressed.
610  if (DiagLevel >= DiagnosticIDs::Error) {
611  ++Diag.TrapNumErrorsOccurred;
612  if (isUnrecoverable(DiagID))
613  ++Diag.TrapNumUnrecoverableErrorsOccurred;
614  }
615 
616  if (Diag.SuppressAllDiagnostics)
617  return false;
618 
619  if (DiagLevel != DiagnosticIDs::Note) {
620  // Record that a fatal error occurred only when we see a second
621  // non-note diagnostic. This allows notes to be attached to the
622  // fatal error, but suppresses any diagnostics that follow those
623  // notes.
624  if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
625  Diag.FatalErrorOccurred = true;
626 
627  Diag.LastDiagLevel = DiagLevel;
628  }
629 
630  // If a fatal error has already been emitted, silence all subsequent
631  // diagnostics.
632  if (Diag.FatalErrorOccurred) {
633  if (DiagLevel >= DiagnosticIDs::Error &&
634  Diag.Client->IncludeInDiagnosticCounts()) {
635  ++Diag.NumErrors;
636  }
637 
638  return false;
639  }
640 
641  // If the client doesn't care about this message, don't issue it. If this is
642  // a note and the last real diagnostic was ignored, ignore it too.
643  if (DiagLevel == DiagnosticIDs::Ignored ||
644  (DiagLevel == DiagnosticIDs::Note &&
645  Diag.LastDiagLevel == DiagnosticIDs::Ignored))
646  return false;
647 
648  if (DiagLevel >= DiagnosticIDs::Error) {
649  if (isUnrecoverable(DiagID))
650  Diag.UnrecoverableErrorOccurred = true;
651 
652  // Warnings which have been upgraded to errors do not prevent compilation.
653  if (isDefaultMappingAsError(DiagID))
654  Diag.UncompilableErrorOccurred = true;
655 
656  Diag.ErrorOccurred = true;
657  if (Diag.Client->IncludeInDiagnosticCounts()) {
658  ++Diag.NumErrors;
659  }
660 
661  // If we've emitted a lot of errors, emit a fatal error instead of it to
662  // stop a flood of bogus errors.
663  if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
664  DiagLevel == DiagnosticIDs::Error) {
665  Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
666  return false;
667  }
668  }
669 
670  // Finally, report it.
671  EmitDiag(Diag, DiagLevel);
672  return true;
673 }
674 
675 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
676  Diagnostic Info(&Diag);
677  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
678 
679  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
680  if (Diag.Client->IncludeInDiagnosticCounts()) {
681  if (DiagLevel == DiagnosticIDs::Warning)
682  ++Diag.NumWarnings;
683  }
684 
685  Diag.CurDiagID = ~0U;
686 }
687 
688 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
689  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
690  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
691  // Custom diagnostics.
692  return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
693  }
694 
695  // Only errors may be unrecoverable.
696  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
697  return false;
698 
699  if (DiagID == diag::err_unavailable ||
700  DiagID == diag::err_unavailable_message)
701  return false;
702 
703  // Currently we consider all ARC errors as recoverable.
704  if (isARCDiagnostic(DiagID))
705  return false;
706 
707  return true;
708 }
709 
710 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
711  unsigned cat = getCategoryNumberForDiag(DiagID);
712  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
713 }
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:368
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:62
#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
iterator begin() const
Definition: Type.h:4072
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:1726
SourceManager & getSourceManager() const
Definition: Diagnostic.h:379
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:44
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
Definition: Diagnostic.cpp:980
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.
iterator end() const
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...
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.
const TemplateArgument * iterator
Definition: Type.h:4070
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
Flavor
Flavors of diagnostics we can emit.
Definition: DiagnosticIDs.h:73
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
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.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1137
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...