clang  12.0.0git
DiagnosticIDs.cpp
Go to the documentation of this file.
1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Diagnostic IDs-related interfaces.
10 //
11 //===----------------------------------------------------------------------===//
12 
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include <map>
21 using namespace clang;
22 
23 //===----------------------------------------------------------------------===//
24 // Builtin Diagnostic information
25 //===----------------------------------------------------------------------===//
26 
27 namespace {
28 
29 // Diagnostic classes.
30 enum {
31  CLASS_NOTE = 0x01,
32  CLASS_REMARK = 0x02,
33  CLASS_WARNING = 0x03,
34  CLASS_EXTENSION = 0x04,
35  CLASS_ERROR = 0x05
36 };
37 
38 struct StaticDiagInfoRec {
39  uint16_t DiagID;
40  unsigned DefaultSeverity : 3;
41  unsigned Class : 3;
42  unsigned SFINAE : 2;
43  unsigned WarnNoWerror : 1;
44  unsigned WarnShowInSystemHeader : 1;
45  unsigned Category : 6;
46 
47  uint16_t OptionGroupIndex;
48 
49  uint16_t DescriptionLen;
50  const char *DescriptionStr;
51 
52  unsigned getOptionGroupIndex() const {
53  return OptionGroupIndex;
54  }
55 
56  StringRef getDescription() const {
57  return StringRef(DescriptionStr, DescriptionLen);
58  }
59 
60  diag::Flavor getFlavor() const {
61  return Class == CLASS_REMARK ? diag::Flavor::Remark
63  }
64 
65  bool operator<(const StaticDiagInfoRec &RHS) const {
66  return DiagID < RHS.DiagID;
67  }
68 };
69 
70 #define STRINGIFY_NAME(NAME) #NAME
71 #define VALIDATE_DIAG_SIZE(NAME) \
72  static_assert( \
73  static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
74  static_cast<unsigned>(diag::DIAG_START_##NAME) + \
75  static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
76  STRINGIFY_NAME( \
77  DIAG_SIZE_##NAME) " is insufficient to contain all " \
78  "diagnostics, it may need to be made larger in " \
79  "DiagnosticIDs.h.");
80 VALIDATE_DIAG_SIZE(COMMON)
81 VALIDATE_DIAG_SIZE(DRIVER)
82 VALIDATE_DIAG_SIZE(FRONTEND)
83 VALIDATE_DIAG_SIZE(SERIALIZATION)
85 VALIDATE_DIAG_SIZE(PARSE)
88 VALIDATE_DIAG_SIZE(CROSSTU)
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, std::string(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 
316 
318 
319 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
320 /// and level. If this is the first request for this diagnostic, it is
321 /// registered and created, otherwise the existing ID is returned.
322 ///
323 /// \param FormatString A fixed diagnostic format string that will be hashed and
324 /// mapped to a unique DiagID.
325 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
326  if (!CustomDiagInfo)
327  CustomDiagInfo.reset(new diag::CustomDiagInfo());
328  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
329 }
330 
331 
332 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
333 /// level of the specified diagnostic ID is a Warning or Extension.
334 /// This only works on builtin diagnostics, not custom ones, and is not legal to
335 /// call on NOTEs.
337  return DiagID < diag::DIAG_UPPER_LIMIT &&
338  getBuiltinDiagClass(DiagID) != CLASS_ERROR;
339 }
340 
341 /// Determine whether the given built-in diagnostic ID is a
342 /// Note.
343 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
344  return DiagID < diag::DIAG_UPPER_LIMIT &&
345  getBuiltinDiagClass(DiagID) == CLASS_NOTE;
346 }
347 
348 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
349 /// ID is for an extension of some sort. This also returns EnabledByDefault,
350 /// which is set to indicate whether the diagnostic is ignored by default (in
351 /// which case -pedantic enables it) or treated as a warning/error by default.
352 ///
354  bool &EnabledByDefault) {
355  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
356  getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
357  return false;
358 
359  EnabledByDefault =
361  return true;
362 }
363 
365  if (DiagID >= diag::DIAG_UPPER_LIMIT)
366  return false;
367 
369 }
370 
371 /// getDescription - Given a diagnostic ID, return a description of the
372 /// issue.
373 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
374  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
375  return Info->getDescription();
376  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
377  return CustomDiagInfo->getDescription(DiagID);
378 }
379 
381  switch (SV) {
383  return DiagnosticIDs::Ignored;
385  return DiagnosticIDs::Remark;
387  return DiagnosticIDs::Warning;
389  return DiagnosticIDs::Error;
391  return DiagnosticIDs::Fatal;
392  }
393  llvm_unreachable("unexpected severity");
394 }
395 
396 /// getDiagnosticLevel - Based on the way the client configured the
397 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
398 /// by consumable the DiagnosticClient.
400 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
401  const DiagnosticsEngine &Diag) const {
402  // Handle custom diagnostics, which cannot be mapped.
403  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
404  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
405  return CustomDiagInfo->getLevel(DiagID);
406  }
407 
408  unsigned DiagClass = getBuiltinDiagClass(DiagID);
409  if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
410  return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
411 }
412 
413 /// Based on the way the client configured the Diagnostic
414 /// object, classify the specified diagnostic ID into a Level, consumable by
415 /// the DiagnosticClient.
416 ///
417 /// \param Loc The source location we are interested in finding out the
418 /// diagnostic state. Can be null in order to query the latest state.
420 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
421  const DiagnosticsEngine &Diag) const {
422  assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
423 
424  // Specific non-error diagnostics may be mapped to various levels from ignored
425  // to error. Errors can only be mapped to fatal.
427 
428  // Get the mapping information, or compute it lazily.
429  DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
430  DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
431 
432  // TODO: Can a null severity really get here?
433  if (Mapping.getSeverity() != diag::Severity())
434  Result = Mapping.getSeverity();
435 
436  // Upgrade ignored diagnostics if -Weverything is enabled.
437  if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
438  !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
439  Result = diag::Severity::Warning;
440 
441  // Ignore -pedantic diagnostics inside __extension__ blocks.
442  // (The diagnostics controlled by -pedantic are the extension diagnostics
443  // that are not enabled by default.)
444  bool EnabledByDefault = false;
445  bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
446  if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
448 
449  // For extension diagnostics that haven't been explicitly mapped, check if we
450  // should upgrade the diagnostic.
451  if (IsExtensionDiag && !Mapping.isUser())
452  Result = std::max(Result, State->ExtBehavior);
453 
454  // At this point, ignored errors can no longer be upgraded.
455  if (Result == diag::Severity::Ignored)
456  return Result;
457 
458  // Honor -w: this disables all messages which which are not Error/Fatal by
459  // default (disregarding attempts to upgrade severity from Warning to Error),
460  // as well as disabling all messages which are currently mapped to Warning
461  // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
462  // diagnostic.)
463  if (State->IgnoreAllWarnings) {
464  if (Result == diag::Severity::Warning ||
465  (Result >= diag::Severity::Error &&
466  !isDefaultMappingAsError((diag::kind)DiagID)))
468  }
469 
470  // If -Werror is enabled, map warnings to errors unless explicitly disabled.
471  if (Result == diag::Severity::Warning) {
472  if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
473  Result = diag::Severity::Error;
474  }
475 
476  // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
477  // disabled.
478  if (Result == diag::Severity::Error) {
479  if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
480  Result = diag::Severity::Fatal;
481  }
482 
483  // If explicitly requested, map fatal errors to errors.
484  if (Result == diag::Severity::Fatal &&
485  Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
486  Result = diag::Severity::Error;
487 
488  // Custom diagnostics always are emitted in system headers.
489  bool ShowInSystemHeader =
490  !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
491 
492  // If we are in a system header, we ignore it. We look at the diagnostic class
493  // because we also want to ignore extensions and warnings in -Werror and
494  // -pedantic-errors modes, which *map* warnings/extensions to errors.
495  if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
497  Diag.getSourceManager().getExpansionLoc(Loc)))
499 
500  return Result;
501 }
502 
503 #define GET_DIAG_ARRAYS
504 #include "clang/Basic/DiagnosticGroups.inc"
505 #undef GET_DIAG_ARRAYS
506 
507 namespace {
508  struct WarningOption {
509  uint16_t NameOffset;
510  uint16_t Members;
511  uint16_t SubGroups;
512 
513  // String is stored with a pascal-style length byte.
514  StringRef getName() const {
515  return StringRef(DiagGroupNames + NameOffset + 1,
516  DiagGroupNames[NameOffset]);
517  }
518  };
519 }
520 
521 // Second the table of options, sorted by name for fast binary lookup.
522 static const WarningOption OptionTable[] = {
523 #define GET_DIAG_TABLE
524 #include "clang/Basic/DiagnosticGroups.inc"
525 #undef GET_DIAG_TABLE
526 };
527 
528 /// getWarningOptionForDiag - Return the lowest-level warning option that
529 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
530 /// the diagnostic, this returns null.
531 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
532  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
533  return OptionTable[Info->getOptionGroupIndex()].getName();
534  return StringRef();
535 }
536 
537 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
538  std::vector<std::string> Res;
539  for (size_t I = 1; DiagGroupNames[I] != '\0';) {
540  std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
541  I += DiagGroupNames[I] + 1;
542  Res.push_back("-W" + Diag);
543  Res.push_back("-Wno-" + Diag);
544  }
545 
546  return Res;
547 }
548 
549 /// Return \c true if any diagnostics were found in this group, even if they
550 /// were filtered out due to having the wrong flavor.
552  const WarningOption *Group,
554  // An empty group is considered to be a warning group: we have empty groups
555  // for GCC compatibility, and GCC does not have remarks.
556  if (!Group->Members && !Group->SubGroups)
557  return Flavor == diag::Flavor::Remark;
558 
559  bool NotFound = true;
560 
561  // Add the members of the option diagnostic set.
562  const int16_t *Member = DiagArrays + Group->Members;
563  for (; *Member != -1; ++Member) {
564  if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
565  NotFound = false;
566  Diags.push_back(*Member);
567  }
568  }
569 
570  // Add the members of the subgroups.
571  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
572  for (; *SubGroups != (int16_t)-1; ++SubGroups)
573  NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
574  Diags);
575 
576  return NotFound;
577 }
578 
579 bool
581  SmallVectorImpl<diag::kind> &Diags) const {
582  auto Found = llvm::partition_point(
583  OptionTable, [=](const WarningOption &O) { return O.getName() < Group; });
584  if (Found == std::end(OptionTable) || Found->getName() != Group)
585  return true; // Option not found.
586 
587  return ::getDiagnosticsInGroup(Flavor, Found, Diags);
588 }
589 
591  std::vector<diag::kind> &Diags) {
592  for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
593  if (StaticDiagInfo[i].getFlavor() == Flavor)
594  Diags.push_back(StaticDiagInfo[i].DiagID);
595 }
596 
598  StringRef Group) {
599  StringRef Best;
600  unsigned BestDistance = Group.size() + 1; // Sanity threshold.
601  for (const WarningOption &O : OptionTable) {
602  // Don't suggest ignored warning flags.
603  if (!O.Members && !O.SubGroups)
604  continue;
605 
606  unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
607  if (Distance > BestDistance)
608  continue;
609 
610  // Don't suggest groups that are not of this kind.
612  if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
613  continue;
614 
615  if (Distance == BestDistance) {
616  // Two matches with the same distance, don't prefer one over the other.
617  Best = "";
618  } else if (Distance < BestDistance) {
619  // This is a better match.
620  Best = O.getName();
621  BestDistance = Distance;
622  }
623  }
624 
625  return Best;
626 }
627 
628 /// ProcessDiag - This is the method used to report a diagnostic that is
629 /// finally fully formed.
630 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
631  Diagnostic Info(&Diag);
632 
633  assert(Diag.getClient() && "DiagnosticClient not set!");
634 
635  // Figure out the diagnostic level of this message.
636  unsigned DiagID = Info.getID();
637  DiagnosticIDs::Level DiagLevel
638  = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
639 
640  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
641  // or diagnostics are suppressed.
642  if (DiagLevel >= DiagnosticIDs::Error) {
643  ++Diag.TrapNumErrorsOccurred;
644  if (isUnrecoverable(DiagID))
645  ++Diag.TrapNumUnrecoverableErrorsOccurred;
646  }
647 
648  if (Diag.SuppressAllDiagnostics)
649  return false;
650 
651  if (DiagLevel != DiagnosticIDs::Note) {
652  // Record that a fatal error occurred only when we see a second
653  // non-note diagnostic. This allows notes to be attached to the
654  // fatal error, but suppresses any diagnostics that follow those
655  // notes.
656  if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
657  Diag.FatalErrorOccurred = true;
658 
659  Diag.LastDiagLevel = DiagLevel;
660  }
661 
662  // If a fatal error has already been emitted, silence all subsequent
663  // diagnostics.
664  if (Diag.FatalErrorOccurred) {
665  if (DiagLevel >= DiagnosticIDs::Error &&
666  Diag.Client->IncludeInDiagnosticCounts()) {
667  ++Diag.NumErrors;
668  }
669 
670  return false;
671  }
672 
673  // If the client doesn't care about this message, don't issue it. If this is
674  // a note and the last real diagnostic was ignored, ignore it too.
675  if (DiagLevel == DiagnosticIDs::Ignored ||
676  (DiagLevel == DiagnosticIDs::Note &&
677  Diag.LastDiagLevel == DiagnosticIDs::Ignored))
678  return false;
679 
680  if (DiagLevel >= DiagnosticIDs::Error) {
681  if (isUnrecoverable(DiagID))
682  Diag.UnrecoverableErrorOccurred = true;
683 
684  // Warnings which have been upgraded to errors do not prevent compilation.
685  if (isDefaultMappingAsError(DiagID))
686  Diag.UncompilableErrorOccurred = true;
687 
688  Diag.ErrorOccurred = true;
689  if (Diag.Client->IncludeInDiagnosticCounts()) {
690  ++Diag.NumErrors;
691  }
692 
693  // If we've emitted a lot of errors, emit a fatal error instead of it to
694  // stop a flood of bogus errors.
695  if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
696  DiagLevel == DiagnosticIDs::Error) {
697  Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
698  return false;
699  }
700  }
701 
702  // Make sure we set FatalErrorOccurred to ensure that the notes from the
703  // diagnostic that caused `fatal_too_many_errors` won't be emitted.
704  if (Diag.CurDiagID == diag::fatal_too_many_errors)
705  Diag.FatalErrorOccurred = true;
706  // Finally, report it.
707  EmitDiag(Diag, DiagLevel);
708  return true;
709 }
710 
711 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
712  Diagnostic Info(&Diag);
713  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
714 
715  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
716  if (Diag.Client->IncludeInDiagnosticCounts()) {
717  if (DiagLevel == DiagnosticIDs::Warning)
718  ++Diag.NumWarnings;
719  }
720 
721  Diag.CurDiagID = ~0U;
722 }
723 
724 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
725  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
726  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
727  // Custom diagnostics.
728  return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
729  }
730 
731  // Only errors may be unrecoverable.
732  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
733  return false;
734 
735  if (DiagID == diag::err_unavailable ||
736  DiagID == diag::err_unavailable_message)
737  return false;
738 
739  // Currently we consider all ARC errors as recoverable.
740  if (isARCDiagnostic(DiagID))
741  return false;
742 
743  return true;
744 }
745 
746 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
747  unsigned cat = getCategoryNumberForDiag(DiagID);
748  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
749 }
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:520
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
SourceManager & getSourceManager() const
Definition: Diagnostic.h:532
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:79
#define CATEGORY(NAME, PREV)
unsigned getID() const
Definition: Diagnostic.h:1364
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:2021
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. ...
const SourceLocation & getLocation() const
Definition: Diagnostic.h:1365
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:153
static bool isBuiltinWarningOrExtension(unsigned DiagID)
Return true if the unmapped diagnostic levelof the specified diagnostic ID is a Warning or Extension...
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="", StringRef Arg3="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
Definition: Diagnostic.cpp:153
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...
unsigned Offset
Definition: Format.cpp:2020
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
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
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:538
Flavor
Flavors of diagnostics we can emit.
Definition: DiagnosticIDs.h:90
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.
Stencil cat(Ts &&... Parts)
Concatenates 0+ stencil pieces into a single stencil.
Definition: Stencil.h:64
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.
static std::string getName(const CallEvent &Call)
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[]
__DEVICE__ int max(int __a, int __b)
void setSeverity(diag::Severity Value)
StringRef getDescription(unsigned DiagID) const
Given a diagnostic ID, return a description of the issue.
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:156
Do not present this diagnostic, ignore it.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:60
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1354
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