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