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